Adding ability to upload files on s3.
To enable file upload on S3 you need to enable the configuration setting in c_configuration table for s3. The S3 credentials (access_key, secret_key, bucket_name) in a m_external_services table. m_client table is normalised into m_client and m_image table. The relation between m_client and m_image is one-to-one for now. To persist the storage type(s3 or filesystem) a column had been added to m_document. MISOFX-69 Adding db migrations for s3 support MIFOSX-69 Adding method to return boolean value of S3 config MIFOSX-69 - Priti/Harsha - Refactoring Code, extracted interface for Documents upload MIFOSX-69 Refactored to add S3 Support for file upload. Modified saveDocs to throw Document Management Exception instead of IO exception MIFOSX-69 Adding S3 support for file upload MIFOSX-69 - Adding S3 support for Image upload MIFOSX-69 Adding factory to get instance of data store as per s3 configuration MIFOSX-69 Changing table s3_details to generic tabe for external services, adding column to store the storage type in m_documents table MIFOSX-69 Fetching S3 details from database MIFOSX-69 Adding document storage type while creating a document MIFOSX-69 Normalising client table to create an image table Refactoring ClientImage code to save client image in m_image table Refactored code to get document as file MIFOSX-69 Retreiving documents from S3 MIFOSX-69 Refactored ClientData to store ImageData MIFOSX-69 Retrieving images from S3, Modifying Base64 to encode from byte array instead of file in CLientImagesApiResource MIFOSX-69 Refactored code to delete client image MIFOSX-69 Deleting Images from S3 Refactored DocumentStore to return StoreType from string value MIFOSX-69 Refactored to move document deletion responsibility to storageType MIFOSX-69 Giving more appropriate name to getInstance methods of DocumentStoreFactory as per the instance creation criteria MIFOSX-69 Deleting Documents from S3 MIFOSX-69 Removing unnecessary s3_param from migration MIFOSX-69 Adding ability to update document and update doc store type MIFOSX-69 Renaming method to follow java conventions MIFOSX-69 Adding filename to error log for s3 file retrieval Adding data migrations and changing the version for migration file
This commit is contained in:
@@ -0,0 +1,28 @@
|
|||||||
|
INSERT INTO c_configuration (name,enabled) VALUES ('amazon-S3',0);
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS m_external_services (
|
||||||
|
name VARCHAR(150) NOT NULL,
|
||||||
|
value VARCHAR(250),
|
||||||
|
UNIQUE(name)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO m_external_services (name) VALUES ('s3_bucket_name');
|
||||||
|
INSERT INTO m_external_services (name) VALUES ('s3_access_key');
|
||||||
|
INSERT INTO m_external_services (name) VALUES ('s3_secret_key');
|
||||||
|
|
||||||
|
ALTER TABLE m_document ADD COLUMN storage_type varchar(50);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `m_image`(
|
||||||
|
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||||
|
`client_id` BIGINT NOT NULL,
|
||||||
|
`key` varchar(500),
|
||||||
|
`storage_type` varchar(50),
|
||||||
|
FOREIGN KEY (`client_id`) REFERENCES m_client(`id`),
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE(client_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
UPDATE m_document set storage_type='file_system';
|
||||||
|
|
||||||
|
insert into m_image (`client_id`,`key`,`storage_type`) select id,`image_key`,'file_system' from m_client where `image_key` IS NOT NULL;
|
||||||
+1
@@ -8,4 +8,5 @@ package org.mifosplatform.infrastructure.configuration.domain;
|
|||||||
public interface ConfigurationDomainService {
|
public interface ConfigurationDomainService {
|
||||||
|
|
||||||
boolean isMakerCheckerEnabledForTask(String taskPermissionCode);
|
boolean isMakerCheckerEnabledForTask(String taskPermissionCode);
|
||||||
|
boolean isAmazonS3Enabled();
|
||||||
}
|
}
|
||||||
+5
@@ -39,4 +39,9 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService
|
|||||||
|
|
||||||
return thisTask.hasMakerCheckerEnabled() && property.isEnabled();
|
return thisTask.hasMakerCheckerEnabled() && property.isEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAmazonS3Enabled(){
|
||||||
|
return this.globalConfigurationRepository.findOneByName("amazon-S3").isEnabled();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
package org.mifosplatform.infrastructure.configuration.domain;
|
||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.UniqueConstraint;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "m_external_services", uniqueConstraints = { @UniqueConstraint(columnNames = ("name"))})
|
||||||
|
public class ExternalServiceProperty extends AbstractPersistable<Long> {
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
@Column(name = "name", nullable = false)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column(name = "value", nullable = false)
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
public ExternalServiceProperty(final String name, final String value) {
|
||||||
|
this.name = name;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExternalServiceProperty() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue(){
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package org.mifosplatform.infrastructure.configuration.domain;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||||
|
|
||||||
|
public interface ExternalServiceRepository extends JpaRepository<ExternalServiceProperty, Long>,
|
||||||
|
JpaSpecificationExecutor<ExternalServiceProperty> {
|
||||||
|
|
||||||
|
ExternalServiceProperty findOneByName(String name);
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
package org.mifosplatform.infrastructure.configuration.domain;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class ExternalServicesDomainService {
|
||||||
|
private ExternalServiceRepository externalServiceRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public ExternalServicesDomainService(final ExternalServiceRepository externalServiceRepository) {
|
||||||
|
this.externalServiceRepository = externalServiceRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue(String name){
|
||||||
|
return externalServiceRepository.findOneByName(name).getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
package org.mifosplatform.infrastructure.core.service;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.api.ApiConstants;
|
||||||
|
import org.mifosplatform.infrastructure.core.domain.Base64EncodedImage;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.command.DocumentCommand;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.data.DocumentData;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.data.FileData;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.exception.DocumentManagementException;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.exception.DocumentNotFoundException;
|
||||||
|
import org.mifosplatform.portfolio.client.data.ImageData;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public abstract class DocumentStore {
|
||||||
|
protected DocumentStoreType type;
|
||||||
|
|
||||||
|
protected Integer maxFileSize = ApiConstants.MAX_FILE_UPLOAD_SIZE_IN_MB;
|
||||||
|
protected Integer maxImageSize = ApiConstants.MAX_IMAGE_UPLOAD_SIZE_IN_MB;
|
||||||
|
|
||||||
|
public abstract String saveDocument(InputStream uploadedInputStream, DocumentCommand documentCommand) throws DocumentManagementException;
|
||||||
|
public abstract void deleteDocument(String documentName, String documentPath) throws DocumentManagementException;
|
||||||
|
public abstract FileData retrieveDocument(DocumentData documentData) throws DocumentNotFoundException;
|
||||||
|
|
||||||
|
public abstract String saveImage(InputStream uploadedInputStream, Long resourceId, String imageName, Long fileSize) throws DocumentManagementException;
|
||||||
|
public abstract String saveImage(Base64EncodedImage base64EncodedImage, Long resourceId, String imageName) throws DocumentManagementException;
|
||||||
|
public abstract void deleteImage(final Long resourceId, final String location);
|
||||||
|
public abstract ImageData retrieveImage(ImageData imageData);
|
||||||
|
|
||||||
|
public abstract DocumentStoreType getType();
|
||||||
|
|
||||||
|
protected void validateFileSizeWithinPermissibleRange(Long fileSize, String name, int maxFileSize) {
|
||||||
|
/**
|
||||||
|
* Using Content-Length gives me size of the entire request, which is
|
||||||
|
* good enough for now for a fast fail as the length of the rest of the
|
||||||
|
* content i.e name and description while compared to the uploaded file
|
||||||
|
* size is negligible
|
||||||
|
**/
|
||||||
|
if (fileSize != null && ((fileSize / (1024 * 1024)) > maxFileSize)) {
|
||||||
|
throw new DocumentManagementException(name, fileSize,
|
||||||
|
maxFileSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DocumentStoreType getDocumentStoreType(String documentStoreType){
|
||||||
|
if (documentStoreType.equals(DocumentStoreType.FILE_SYSTEM.getValue())) {
|
||||||
|
return DocumentStoreType.FILE_SYSTEM;
|
||||||
|
} else {
|
||||||
|
return DocumentStoreType.S3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
package org.mifosplatform.infrastructure.core.service;
|
||||||
|
|
||||||
|
import com.amazonaws.services.s3.AmazonS3Client;
|
||||||
|
import org.mifosplatform.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||||
|
import org.mifosplatform.infrastructure.configuration.domain.ExternalServicesDomainService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class DocumentStoreFactory {
|
||||||
|
|
||||||
|
private ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public DocumentStoreFactory(ApplicationContext applicationContext) {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DocumentStore getInstanceFromConfiguration(){
|
||||||
|
ConfigurationDomainService configurationDomainServiceJpa = applicationContext.getBean("configurationDomainServiceJpa", ConfigurationDomainService.class);
|
||||||
|
if(configurationDomainServiceJpa.isAmazonS3Enabled()){
|
||||||
|
return createS3DocumentStore();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new FileSystemDocumentStore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DocumentStore getInstanceFromStorageType(DocumentStoreType documentStoreType){
|
||||||
|
if(documentStoreType == DocumentStoreType.FILE_SYSTEM){
|
||||||
|
return new FileSystemDocumentStore();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return createS3DocumentStore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private DocumentStore createS3DocumentStore() {
|
||||||
|
AmazonS3Client s3Client = applicationContext.getBean("s3ClientFactory", S3ClientFactory.class).getS3Client();
|
||||||
|
ExternalServicesDomainService externalServicesDomainService = applicationContext.getBean("externalServicesDomainService", ExternalServicesDomainService.class);
|
||||||
|
return new S3DocumentStore(externalServicesDomainService.getValue("s3_bucket_name"), s3Client);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
package org.mifosplatform.infrastructure.core.service;
|
||||||
|
|
||||||
|
public enum DocumentStoreType {
|
||||||
|
FILE_SYSTEM("file_system"), S3("s3");
|
||||||
|
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
DocumentStoreType(String value){
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
+160
@@ -0,0 +1,160 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.infrastructure.core.service;
|
||||||
|
|
||||||
|
import com.lowagie.text.pdf.codec.Base64;
|
||||||
|
import org.mifosplatform.infrastructure.core.domain.Base64EncodedImage;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.command.DocumentCommand;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.data.DocumentData;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.data.FileData;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.exception.DocumentManagementException;
|
||||||
|
import org.mifosplatform.portfolio.client.data.ImageData;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class FileSystemDocumentStore extends DocumentStore {
|
||||||
|
|
||||||
|
private final static Logger logger = LoggerFactory.getLogger(FileSystemDocumentStore.class);
|
||||||
|
|
||||||
|
public static final String MIFOSX_BASE_DIR = System.getProperty("user.home") + File.separator + ".mifosx";
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String saveDocument(InputStream uploadedInputStream, DocumentCommand documentCommand) throws DocumentManagementException {
|
||||||
|
String documentName = documentCommand.getFileName();
|
||||||
|
String uploadDocumentLocation = generateFileParentDirectory(documentCommand.getParentEntityType(), documentCommand.getParentEntityId());
|
||||||
|
|
||||||
|
validateFileSizeWithinPermissibleRange(documentCommand.getSize(), documentName, maxFileSize);
|
||||||
|
makeDirectories(uploadDocumentLocation);
|
||||||
|
|
||||||
|
String fileLocation = uploadDocumentLocation + File.separator + documentName;
|
||||||
|
|
||||||
|
writeFileToFileSystem(uploadedInputStream, fileLocation);
|
||||||
|
return fileLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String saveImage(InputStream uploadedInputStream, Long resourceId, String imageName, Long fileSize) throws DocumentManagementException {
|
||||||
|
String uploadImageLocation = generateClientImageParentDirectory(resourceId);
|
||||||
|
|
||||||
|
validateFileSizeWithinPermissibleRange(fileSize, imageName, maxImageSize);
|
||||||
|
makeDirectories(uploadImageLocation);
|
||||||
|
|
||||||
|
String fileLocation = uploadImageLocation + File.separator + imageName;
|
||||||
|
|
||||||
|
writeFileToFileSystem(uploadedInputStream, fileLocation);
|
||||||
|
return fileLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String saveImage(Base64EncodedImage base64EncodedImage, Long resourceId, String imageName) throws DocumentManagementException {
|
||||||
|
String uploadImageLocation = generateClientImageParentDirectory(resourceId);
|
||||||
|
|
||||||
|
makeDirectories(uploadImageLocation);
|
||||||
|
|
||||||
|
String fileLocation = uploadImageLocation + File.separator + imageName + base64EncodedImage.getFileExtension();
|
||||||
|
try {
|
||||||
|
OutputStream out = new FileOutputStream(new File(fileLocation));
|
||||||
|
byte[] imgBytes = Base64.decode(base64EncodedImage.getBase64EncodedString());
|
||||||
|
out.write(imgBytes);
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
}catch (IOException ioe){
|
||||||
|
throw new DocumentManagementException(ioe.getMessage());
|
||||||
|
}
|
||||||
|
return fileLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteImage(final Long resourceId, final String location) {
|
||||||
|
final boolean fileDeleted = deleteFile(location);
|
||||||
|
if (!fileDeleted) {
|
||||||
|
// no need to throw an Error, simply log a warning
|
||||||
|
logger.warn("Unable to delete image associated with clients with Id " + resourceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteDocument(String documentName, String documentPath) throws DocumentManagementException{
|
||||||
|
final boolean fileDeleted = deleteFile(documentPath);
|
||||||
|
if (!fileDeleted) { throw new DocumentManagementException(documentName); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean deleteFile(String documentPath) {
|
||||||
|
final File fileToBeDeleted = new File(documentPath);
|
||||||
|
return fileToBeDeleted.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DocumentStoreType getType() {
|
||||||
|
return DocumentStoreType.FILE_SYSTEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileData retrieveDocument(DocumentData documentData){
|
||||||
|
File file = new File(documentData.fileLocation());
|
||||||
|
return new FileData(file, documentData.fileName(), documentData.contentType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ImageData retrieveImage(ImageData imageData) {
|
||||||
|
File file = new File(imageData.imageKey());
|
||||||
|
imageData.setContent(file);
|
||||||
|
return imageData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the directory path for storing the new document
|
||||||
|
*
|
||||||
|
* @param entityType
|
||||||
|
* @param entityId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String generateFileParentDirectory(String entityType, Long entityId) {
|
||||||
|
return FileSystemDocumentStore.MIFOSX_BASE_DIR + File.separator + ThreadLocalContextUtil.getTenant().getName().replaceAll(" ", "").trim()
|
||||||
|
+ File.separator + "documents" + File.separator + entityType + File.separator + entityId + File.separator
|
||||||
|
+ RandomStringGenerator.generateRandomString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate directory path for storing new Image
|
||||||
|
*/
|
||||||
|
private String generateClientImageParentDirectory(final Long resourceId) {
|
||||||
|
return FileSystemDocumentStore.MIFOSX_BASE_DIR + File.separator + ThreadLocalContextUtil.getTenant().getName().replaceAll(" ", "").trim()
|
||||||
|
+ File.separator + "images" + File.separator + "clients" + File.separator + resourceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively create the directory if it does not exist *
|
||||||
|
*/
|
||||||
|
private void makeDirectories(String uploadDocumentLocation) {
|
||||||
|
if (!new File(uploadDocumentLocation).isDirectory()) {
|
||||||
|
new File(uploadDocumentLocation).mkdirs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void writeFileToFileSystem(InputStream uploadedInputStream, String fileLocation) throws DocumentManagementException {
|
||||||
|
|
||||||
|
try {
|
||||||
|
OutputStream out = new FileOutputStream(new File(fileLocation));
|
||||||
|
int read = 0;
|
||||||
|
byte[] bytes = new byte[1024];
|
||||||
|
|
||||||
|
while ((read = uploadedInputStream.read(bytes)) != -1) {
|
||||||
|
out.write(bytes, 0, read);
|
||||||
|
}
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
} catch (IOException ioException) {
|
||||||
|
throw new DocumentManagementException("IO Exception caught while writing to FileSystem" + ioException.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
-234
@@ -1,234 +0,0 @@
|
|||||||
/**
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
||||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
package org.mifosplatform.infrastructure.core.service;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
|
||||||
import org.mifosplatform.infrastructure.core.domain.Base64EncodedImage;
|
|
||||||
import org.mifosplatform.infrastructure.core.exception.ImageDataURLNotValidException;
|
|
||||||
import org.mifosplatform.infrastructure.core.exception.ImageUploadException;
|
|
||||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
|
||||||
import org.mifosplatform.infrastructure.documentmanagement.exception.DocumentManagementException;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import com.lowagie.text.pdf.codec.Base64;
|
|
||||||
|
|
||||||
public class FileUtils {
|
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(FileUtils.class);
|
|
||||||
|
|
||||||
public static final String MIFOSX_BASE_DIR = System.getProperty("user.home") + File.separator + ".mifosx";
|
|
||||||
|
|
||||||
public static enum IMAGE_MIME_TYPE {
|
|
||||||
GIF("image/gif"), JPEG("image/jpeg"), PNG("image/png");
|
|
||||||
|
|
||||||
private final String value;
|
|
||||||
|
|
||||||
private IMAGE_MIME_TYPE(final String value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue() {
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public static enum IMAGE_FILE_EXTENSION {
|
|
||||||
GIF(".gif"), JPEG(".jpeg"), JPG(".jpg"), PNG(".png");
|
|
||||||
|
|
||||||
private final String value;
|
|
||||||
|
|
||||||
private IMAGE_FILE_EXTENSION(final String value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue() {
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public static enum IMAGE_DATA_URI_SUFFIX {
|
|
||||||
GIF("data:" + IMAGE_MIME_TYPE.GIF.getValue() + ";base64,"), JPEG("data:" + IMAGE_MIME_TYPE.JPEG.getValue() + ";base64,"), PNG(
|
|
||||||
"data:" + IMAGE_MIME_TYPE.PNG.getValue() + ";base64,");
|
|
||||||
|
|
||||||
private final String value;
|
|
||||||
|
|
||||||
private IMAGE_DATA_URI_SUFFIX(final String value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue() {
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public static Random random = new Random();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a random String
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String generateRandomString() {
|
|
||||||
String characters = "abcdefghijklmnopqrstuvwxyz123456789";
|
|
||||||
int length = generateRandomNumber();
|
|
||||||
char[] text = new char[length];
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
text[i] = characters.charAt(random.nextInt(characters.length()));
|
|
||||||
}
|
|
||||||
return new String(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a random number between 5 to 16
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static int generateRandomNumber() {
|
|
||||||
Random randomGenerator = new Random();
|
|
||||||
return randomGenerator.nextInt(11) + 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate the directory path for storing the new document
|
|
||||||
*
|
|
||||||
* @param entityType
|
|
||||||
* @param entityId
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String generateFileParentDirectory(String entityType, Long entityId) {
|
|
||||||
return FileUtils.MIFOSX_BASE_DIR + File.separator + ThreadLocalContextUtil.getTenant().getName().replaceAll(" ", "").trim()
|
|
||||||
+ File.separator + "documents" + File.separator + entityType + File.separator + entityId + File.separator
|
|
||||||
+ FileUtils.generateRandomString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate directory path for storing new Image
|
|
||||||
*/
|
|
||||||
public static String generateClientImageParentDirectory(final Long resourceId) {
|
|
||||||
return FileUtils.MIFOSX_BASE_DIR + File.separator + ThreadLocalContextUtil.getTenant().getName().replaceAll(" ", "").trim()
|
|
||||||
+ File.separator + "images" + File.separator + "clients" + File.separator + resourceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param uploadedInputStream
|
|
||||||
* @param uploadedFileLocation
|
|
||||||
* @return
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public static String saveToFileSystem(InputStream uploadedInputStream, String uploadedFileLocation, String fileName) throws IOException {
|
|
||||||
String fileLocation = uploadedFileLocation + File.separator + fileName;
|
|
||||||
OutputStream out = new FileOutputStream(new File(fileLocation));
|
|
||||||
int read = 0;
|
|
||||||
byte[] bytes = new byte[1024];
|
|
||||||
|
|
||||||
while ((read = uploadedInputStream.read(bytes)) != -1) {
|
|
||||||
out.write(bytes, 0, read);
|
|
||||||
}
|
|
||||||
out.flush();
|
|
||||||
out.close();
|
|
||||||
return fileLocation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param base64EncodedImage
|
|
||||||
* @param uploadedFileLocation
|
|
||||||
* @param fileName
|
|
||||||
* @return
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public static String saveToFileSystem(Base64EncodedImage base64EncodedImage, String uploadedFileLocation, String fileName)
|
|
||||||
throws IOException {
|
|
||||||
String fileLocation = uploadedFileLocation + File.separator + fileName + base64EncodedImage.getFileExtension();
|
|
||||||
OutputStream out = new FileOutputStream(new File(fileLocation));
|
|
||||||
byte[] imgBytes = Base64.decode(base64EncodedImage.getBase64EncodedString());
|
|
||||||
out.write(imgBytes);
|
|
||||||
out.flush();
|
|
||||||
out.close();
|
|
||||||
return fileLocation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param fileSize
|
|
||||||
* @param name
|
|
||||||
*/
|
|
||||||
public static void validateFileSizeWithinPermissibleRange(Long fileSize, String name, int maxFileSize) {
|
|
||||||
/**
|
|
||||||
* Using Content-Length gives me size of the entire request, which is
|
|
||||||
* good enough for now for a fast fail as the length of the rest of the
|
|
||||||
* content i.e name and description while compared to the uploaded file
|
|
||||||
* size is negligible
|
|
||||||
**/
|
|
||||||
if (fileSize != null && ((fileSize / (1024 * 1024)) > maxFileSize)) { throw new DocumentManagementException(name, fileSize,
|
|
||||||
maxFileSize); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates that passed in Mime type maps to known image mime types
|
|
||||||
*
|
|
||||||
* @param mimeType
|
|
||||||
*/
|
|
||||||
public static void validateImageMimeType(String mimeType) {
|
|
||||||
if (!(mimeType.equalsIgnoreCase(IMAGE_MIME_TYPE.GIF.getValue()) || mimeType.equalsIgnoreCase(IMAGE_MIME_TYPE.JPEG.getValue()) || mimeType
|
|
||||||
.equalsIgnoreCase(IMAGE_MIME_TYPE.PNG.getValue()))) { throw new ImageUploadException(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts Image from a Data URL
|
|
||||||
*
|
|
||||||
* @param mimeType
|
|
||||||
*/
|
|
||||||
public static Base64EncodedImage extractImageFromDataURL(String dataURL) {
|
|
||||||
String fileExtension = "";
|
|
||||||
String base64EncodedString = null;
|
|
||||||
if (StringUtils.startsWith(dataURL, IMAGE_DATA_URI_SUFFIX.GIF.getValue())) {
|
|
||||||
base64EncodedString = dataURL.replaceAll(IMAGE_DATA_URI_SUFFIX.GIF.getValue(), "");
|
|
||||||
fileExtension = IMAGE_FILE_EXTENSION.GIF.getValue();
|
|
||||||
} else if (StringUtils.startsWith(dataURL, IMAGE_DATA_URI_SUFFIX.PNG.getValue())) {
|
|
||||||
base64EncodedString = dataURL.replaceAll(IMAGE_DATA_URI_SUFFIX.PNG.getValue(), "");
|
|
||||||
fileExtension = IMAGE_FILE_EXTENSION.PNG.getValue();
|
|
||||||
} else if (StringUtils.startsWith(dataURL, IMAGE_DATA_URI_SUFFIX.JPEG.getValue())) {
|
|
||||||
base64EncodedString = dataURL.replaceAll(IMAGE_DATA_URI_SUFFIX.JPEG.getValue(), "");
|
|
||||||
fileExtension = IMAGE_FILE_EXTENSION.JPEG.getValue();
|
|
||||||
} else {
|
|
||||||
throw new ImageDataURLNotValidException();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Base64EncodedImage(base64EncodedString, fileExtension);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void validateClientImageNotEmpty(String imageFileName) {
|
|
||||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
|
||||||
if (imageFileName == null) {
|
|
||||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.clientImage.cannot.be.blank");
|
|
||||||
StringBuilder defaultEnglishMessage = new StringBuilder("The parameter image cannot be blank.");
|
|
||||||
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(), defaultEnglishMessage.toString(),
|
|
||||||
"image");
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
|
||||||
dataValidationErrors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void deleteClientImage(final Long resourceId, final String location) {
|
|
||||||
File fileToBeDeleted = new File(location);
|
|
||||||
boolean fileDeleted = fileToBeDeleted.delete();
|
|
||||||
if (!fileDeleted) {
|
|
||||||
// no need to throw an Error, simply log a warning
|
|
||||||
logger.warn("Unable to delete image associated with clients with Id " + resourceId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+105
@@ -0,0 +1,105 @@
|
|||||||
|
package org.mifosplatform.infrastructure.core.service;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||||
|
import org.mifosplatform.infrastructure.core.domain.Base64EncodedImage;
|
||||||
|
import org.mifosplatform.infrastructure.core.exception.ImageDataURLNotValidException;
|
||||||
|
import org.mifosplatform.infrastructure.core.exception.ImageUploadException;
|
||||||
|
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ImageUtils {
|
||||||
|
|
||||||
|
public static enum IMAGE_MIME_TYPE {
|
||||||
|
GIF("image/gif"), JPEG("image/jpeg"), PNG("image/png");
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
private IMAGE_MIME_TYPE(final String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum IMAGE_FILE_EXTENSION {
|
||||||
|
GIF(".gif"), JPEG(".jpeg"), JPG(".jpg"), PNG(".png");
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
private IMAGE_FILE_EXTENSION(final String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum IMAGE_DATA_URI_SUFFIX {
|
||||||
|
GIF("data:" + IMAGE_MIME_TYPE.GIF.getValue() + ";base64,"), JPEG("data:" + IMAGE_MIME_TYPE.JPEG.getValue() + ";base64,"), PNG(
|
||||||
|
"data:" + IMAGE_MIME_TYPE.PNG.getValue() + ";base64,");
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
private IMAGE_DATA_URI_SUFFIX(final String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Validates that passed in Mime type maps to known image mime types
|
||||||
|
*
|
||||||
|
* @param mimeType
|
||||||
|
*/
|
||||||
|
public static void validateImageMimeType(String mimeType) {
|
||||||
|
if (!(mimeType.equalsIgnoreCase(IMAGE_MIME_TYPE.GIF.getValue()) || mimeType.equalsIgnoreCase(IMAGE_MIME_TYPE.JPEG.getValue()) || mimeType
|
||||||
|
.equalsIgnoreCase(IMAGE_MIME_TYPE.PNG.getValue()))) {
|
||||||
|
throw new ImageUploadException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts Image from a Data URL
|
||||||
|
*
|
||||||
|
* @param mimeType
|
||||||
|
*/
|
||||||
|
public static Base64EncodedImage extractImageFromDataURL(String dataURL) {
|
||||||
|
String fileExtension = "";
|
||||||
|
String base64EncodedString = null;
|
||||||
|
if (StringUtils.startsWith(dataURL, IMAGE_DATA_URI_SUFFIX.GIF.getValue())) {
|
||||||
|
base64EncodedString = dataURL.replaceAll(IMAGE_DATA_URI_SUFFIX.GIF.getValue(), "");
|
||||||
|
fileExtension = IMAGE_FILE_EXTENSION.GIF.getValue();
|
||||||
|
} else if (StringUtils.startsWith(dataURL, IMAGE_DATA_URI_SUFFIX.PNG.getValue())) {
|
||||||
|
base64EncodedString = dataURL.replaceAll(IMAGE_DATA_URI_SUFFIX.PNG.getValue(), "");
|
||||||
|
fileExtension = IMAGE_FILE_EXTENSION.PNG.getValue();
|
||||||
|
} else if (StringUtils.startsWith(dataURL, IMAGE_DATA_URI_SUFFIX.JPEG.getValue())) {
|
||||||
|
base64EncodedString = dataURL.replaceAll(IMAGE_DATA_URI_SUFFIX.JPEG.getValue(), "");
|
||||||
|
fileExtension = IMAGE_FILE_EXTENSION.JPEG.getValue();
|
||||||
|
} else {
|
||||||
|
throw new ImageDataURLNotValidException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Base64EncodedImage(base64EncodedString, fileExtension);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void validateClientImageNotEmpty(String imageFileName) {
|
||||||
|
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
|
if (imageFileName == null) {
|
||||||
|
StringBuilder validationErrorCode = new StringBuilder("validation.msg.clientImage.cannot.be.blank");
|
||||||
|
StringBuilder defaultEnglishMessage = new StringBuilder("The parameter image cannot be blank.");
|
||||||
|
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(), defaultEnglishMessage.toString(),
|
||||||
|
"image");
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
||||||
|
dataValidationErrors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
package org.mifosplatform.infrastructure.core.service;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class RandomStringGenerator {
|
||||||
|
public static Random random = new Random();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a random String
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String generateRandomString() {
|
||||||
|
String characters = "abcdefghijklmnopqrstuvwxyz123456789";
|
||||||
|
int length = generateRandomNumber();
|
||||||
|
char[] text = new char[length];
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
text[i] = characters.charAt(random.nextInt(characters.length()));
|
||||||
|
}
|
||||||
|
return new String(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a random number between 5 to 16
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static int generateRandomNumber() {
|
||||||
|
Random randomGenerator = new Random();
|
||||||
|
return randomGenerator.nextInt(11) + 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
package org.mifosplatform.infrastructure.core.service;
|
||||||
|
|
||||||
|
import com.amazonaws.auth.BasicAWSCredentials;
|
||||||
|
import com.amazonaws.services.s3.AmazonS3Client;
|
||||||
|
import org.mifosplatform.infrastructure.configuration.domain.ExternalServicesDomainService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class S3ClientFactory {
|
||||||
|
|
||||||
|
private ExternalServicesDomainService ExternalServicesDomainService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public S3ClientFactory(final ExternalServicesDomainService ExternalServicesDomainService) {
|
||||||
|
this.ExternalServicesDomainService = ExternalServicesDomainService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AmazonS3Client getS3Client() {
|
||||||
|
String s3_access_key = ExternalServicesDomainService.getValue("s3_access_key");
|
||||||
|
String s3_secret_key = ExternalServicesDomainService.getValue("s3_secret_key");
|
||||||
|
return new AmazonS3Client(new BasicAWSCredentials(s3_access_key,s3_secret_key));
|
||||||
|
}
|
||||||
|
}
|
||||||
+201
@@ -0,0 +1,201 @@
|
|||||||
|
package org.mifosplatform.infrastructure.core.service;
|
||||||
|
|
||||||
|
|
||||||
|
import com.amazonaws.AmazonClientException;
|
||||||
|
import com.amazonaws.AmazonServiceException;
|
||||||
|
import com.amazonaws.services.s3.AmazonS3;
|
||||||
|
import com.amazonaws.services.s3.model.*;
|
||||||
|
import com.lowagie.text.pdf.codec.Base64;
|
||||||
|
import org.mifosplatform.infrastructure.core.domain.Base64EncodedImage;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.command.DocumentCommand;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.data.DocumentData;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.data.FileData;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.exception.DocumentManagementException;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.exception.DocumentNotFoundException;
|
||||||
|
import org.mifosplatform.portfolio.client.data.ImageData;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class S3DocumentStore extends DocumentStore {
|
||||||
|
|
||||||
|
private final static Logger logger = LoggerFactory.getLogger(S3DocumentStore.class);
|
||||||
|
|
||||||
|
private final String s3BucketName;
|
||||||
|
private AmazonS3 s3Client;
|
||||||
|
|
||||||
|
public S3DocumentStore(String s3BucketName, AmazonS3 s3Client) {
|
||||||
|
this.s3BucketName = s3BucketName;
|
||||||
|
this.s3Client = s3Client;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String saveDocument(InputStream toUpload, DocumentCommand documentCommand) throws DocumentManagementException {
|
||||||
|
String documentName = documentCommand.getFileName();
|
||||||
|
validateFileSizeWithinPermissibleRange(documentCommand.getSize(), documentName, maxFileSize);
|
||||||
|
|
||||||
|
String uploadDocFolder = generateFileParentDirectory(documentCommand.getParentEntityType(), documentCommand.getParentEntityId());
|
||||||
|
String uploadDocFullPath = uploadDocFolder + File.separator + documentName;
|
||||||
|
|
||||||
|
uploadDocument(toUpload, uploadDocFullPath);
|
||||||
|
return uploadDocFullPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteDocument(String documentName, String documentPath) throws DocumentManagementException {
|
||||||
|
try{
|
||||||
|
deleteObjectFromS3(documentPath);
|
||||||
|
}catch (AmazonServiceException ase){
|
||||||
|
deleteObjectAmazonServiceExceptionMessage(ase);
|
||||||
|
throw new DocumentManagementException(documentName);
|
||||||
|
}catch (AmazonClientException ace){
|
||||||
|
deleteObjectAmazonClientExceptionMessage(ace);
|
||||||
|
throw new DocumentManagementException(documentName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String saveImage(InputStream toUploadInputStream, Long resourceId, String imageName, Long fileSize) throws DocumentManagementException {
|
||||||
|
validateFileSizeWithinPermissibleRange(fileSize, imageName, maxImageSize);
|
||||||
|
|
||||||
|
String uploadImageLocation = generateClientImageParentDirectory(resourceId);
|
||||||
|
String fileLocation = uploadImageLocation + File.separator + imageName;
|
||||||
|
|
||||||
|
uploadDocument(toUploadInputStream, fileLocation);
|
||||||
|
return fileLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String saveImage(Base64EncodedImage base64EncodedImage, Long resourceId, String imageName) throws DocumentManagementException {
|
||||||
|
String uploadImageLocation = generateClientImageParentDirectory(resourceId);
|
||||||
|
String fileLocation = uploadImageLocation + File.separator + imageName + base64EncodedImage.getFileExtension();
|
||||||
|
InputStream toUploadInputStream = new ByteArrayInputStream(Base64.decode(base64EncodedImage.getBase64EncodedString()));
|
||||||
|
|
||||||
|
uploadDocument(toUploadInputStream, fileLocation);
|
||||||
|
return fileLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteImage(Long resourceId, String location) {
|
||||||
|
try {
|
||||||
|
deleteObjectFromS3(location);
|
||||||
|
} catch (AmazonServiceException ase) {
|
||||||
|
deleteObjectAmazonServiceExceptionMessage(ase);
|
||||||
|
logger.warn("Unable to delete image associated with clients with Id " + resourceId);
|
||||||
|
} catch (AmazonClientException ace) {
|
||||||
|
deleteObjectAmazonClientExceptionMessage(ace);
|
||||||
|
logger.warn("Unable to delete image associated with clients with Id " + resourceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteObjectAmazonClientExceptionMessage(AmazonClientException ace) {
|
||||||
|
String message = "Caught an AmazonClientException." +
|
||||||
|
"Error Message: " + ace.getMessage();
|
||||||
|
logger.error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteObjectAmazonServiceExceptionMessage(AmazonServiceException ase) {
|
||||||
|
String message = "Caught an AmazonServiceException." +
|
||||||
|
"Error Message: " + ase.getMessage() +
|
||||||
|
"HTTP Status Code: " + ase.getStatusCode() +
|
||||||
|
"AWS Error Code: " + ase.getErrorCode() +
|
||||||
|
"Error Type: " + ase.getErrorType() +
|
||||||
|
"Request ID: " + ase.getRequestId();
|
||||||
|
logger.error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteObjectFromS3(String location) {
|
||||||
|
s3Client.deleteObject(new DeleteObjectRequest(s3BucketName, location));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DocumentStoreType getType() {
|
||||||
|
return DocumentStoreType.S3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileData retrieveDocument(DocumentData documentData) throws DocumentNotFoundException {
|
||||||
|
FileData fileData = null;
|
||||||
|
String fileName = documentData.fileName();
|
||||||
|
try {
|
||||||
|
logger.info("Downloading an object");
|
||||||
|
S3Object s3object = s3Client.getObject(new GetObjectRequest(s3BucketName, documentData.fileLocation()));
|
||||||
|
fileData = new FileData(s3object.getObjectContent(), fileName, documentData.contentType());
|
||||||
|
} catch (AmazonServiceException ase) {
|
||||||
|
getObjectAmazonServiceExceptionMessage(ase,fileName);
|
||||||
|
throw new DocumentNotFoundException(documentData.getParentEntityType(), documentData.getParentEntityId(), documentData.getId());
|
||||||
|
} catch (AmazonClientException ace) {
|
||||||
|
getObjectAmazonClientExceptionMessage(ace,fileName);
|
||||||
|
throw new DocumentNotFoundException(documentData.getParentEntityType(), documentData.getParentEntityId(), documentData.getId());
|
||||||
|
}
|
||||||
|
return fileData;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ImageData retrieveImage(ImageData imageData) {
|
||||||
|
S3Object s3object = s3Client.getObject(new GetObjectRequest(s3BucketName, imageData.imageKey()));
|
||||||
|
imageData.setContent(s3object.getObjectContent());
|
||||||
|
return imageData;
|
||||||
|
}
|
||||||
|
|
||||||
|
String generateFileParentDirectory(String entityType, Long entityId) {
|
||||||
|
return "documents" + File.separator + entityType + File.separator + entityId + File.separator + RandomStringGenerator.generateRandomString();
|
||||||
|
}
|
||||||
|
|
||||||
|
String generateClientImageParentDirectory(Long resourceId) {
|
||||||
|
return "images" + File.separator + "clients" + File.separator + resourceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void uploadDocument(InputStream inputStream, String s3UploadLocation) throws DocumentManagementException {
|
||||||
|
try {
|
||||||
|
logger.info("Uploading a new object to S3 from a file to " + s3UploadLocation);
|
||||||
|
s3Client.putObject(new PutObjectRequest(this.s3BucketName, s3UploadLocation, inputStream, new ObjectMetadata()));
|
||||||
|
|
||||||
|
} catch (AmazonServiceException ase) {
|
||||||
|
String message = "Caught an AmazonServiceException, which " + "means your request made it " + "to Amazon S3, but was rejected with an error response" +
|
||||||
|
" for some reason. \n Error Message: " + ase.getMessage() +
|
||||||
|
"HTTP Status Code: " + ase.getStatusCode() +
|
||||||
|
"AWS Error Code: " + ase.getErrorCode() +
|
||||||
|
"Error Type: " + ase.getErrorType() +
|
||||||
|
"Request ID: " + ase.getRequestId();
|
||||||
|
|
||||||
|
logger.error(message);
|
||||||
|
throw new DocumentManagementException(message);
|
||||||
|
} catch (AmazonClientException ace) {
|
||||||
|
String message = "Caught an AmazonClientException, which " +
|
||||||
|
"means the client encountered " +
|
||||||
|
"an internal error while trying to " +
|
||||||
|
"communicate with S3, " +
|
||||||
|
"such as not being able to access the network." +
|
||||||
|
"Error Message: " + ace.getMessage();
|
||||||
|
logger.error(message);
|
||||||
|
throw new DocumentManagementException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getObjectAmazonClientExceptionMessage(AmazonClientException ace, String filename) {
|
||||||
|
String message = "Caught an AmazonClientException, which means the client encountered " +
|
||||||
|
"an internal error while trying to communicate with S3, " +
|
||||||
|
"such as not being able to access the network." +
|
||||||
|
"Error Message: " + ace.getMessage() +
|
||||||
|
"FileName: " + filename;
|
||||||
|
|
||||||
|
logger.error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getObjectAmazonServiceExceptionMessage(AmazonServiceException ase, String filename) {
|
||||||
|
String message = "Caught an AmazonServiceException, which means your request made it " +
|
||||||
|
"to Amazon S3, but was rejected with an error response" +
|
||||||
|
" for some reason." +
|
||||||
|
"Error Message: " + ase.getMessage() +
|
||||||
|
"HTTP Status Code: " + ase.getStatusCode() +
|
||||||
|
"AWS Error Code: " + ase.getErrorCode() +
|
||||||
|
"Error Type: " + ase.getErrorType() +
|
||||||
|
"Request ID: " + ase.getRequestId() +
|
||||||
|
"FileName: " + filename;
|
||||||
|
logger.error(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-3
@@ -29,7 +29,7 @@ import javax.ws.rs.core.StreamingOutput;
|
|||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||||
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||||
import org.mifosplatform.infrastructure.core.service.FileUtils;
|
import org.mifosplatform.infrastructure.core.service.FileSystemDocumentStore;
|
||||||
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
|
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
|
||||||
import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData;
|
import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData;
|
||||||
import org.mifosplatform.infrastructure.dataqueries.data.ReportData;
|
import org.mifosplatform.infrastructure.dataqueries.data.ReportData;
|
||||||
@@ -243,7 +243,7 @@ public class ReadReportingServiceImpl implements ReadReportingService {
|
|||||||
if (noPentaho) { throw new PlatformDataIntegrityException("error.msg.no.pentaho", "Pentaho is not enabled",
|
if (noPentaho) { throw new PlatformDataIntegrityException("error.msg.no.pentaho", "Pentaho is not enabled",
|
||||||
"Pentaho is not enabled"); }
|
"Pentaho is not enabled"); }
|
||||||
|
|
||||||
final String reportPath = FileUtils.MIFOSX_BASE_DIR + File.separator + "pentahoReports" + File.separator + reportName + ".prpt";
|
final String reportPath = FileSystemDocumentStore.MIFOSX_BASE_DIR + File.separator + "pentahoReports" + File.separator + reportName + ".prpt";
|
||||||
logger.info("Report path: " + reportPath);
|
logger.info("Report path: " + reportPath);
|
||||||
|
|
||||||
// load report definition
|
// load report definition
|
||||||
@@ -357,7 +357,7 @@ public class ReadReportingServiceImpl implements ReadReportingService {
|
|||||||
@Override
|
@Override
|
||||||
public String retrieveReportPDF(final String reportName, final String type, final Map<String, String> queryParams) {
|
public String retrieveReportPDF(final String reportName, final String type, final Map<String, String> queryParams) {
|
||||||
|
|
||||||
String fileLocation = FileUtils.MIFOSX_BASE_DIR + File.separator + "";
|
String fileLocation = FileSystemDocumentStore.MIFOSX_BASE_DIR + File.separator + "";
|
||||||
if (!new File(fileLocation).isDirectory()) {
|
if (!new File(fileLocation).isDirectory()) {
|
||||||
new File(fileLocation).mkdirs();
|
new File(fileLocation).mkdirs();
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-38
@@ -5,36 +5,16 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.infrastructure.documentmanagement.api;
|
package org.mifosplatform.infrastructure.documentmanagement.api;
|
||||||
|
|
||||||
import java.io.File;
|
import com.sun.jersey.core.header.FormDataContentDisposition;
|
||||||
import java.io.InputStream;
|
import com.sun.jersey.multipart.FormDataBodyPart;
|
||||||
import java.util.Arrays;
|
import com.sun.jersey.multipart.FormDataParam;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
|
||||||
import javax.ws.rs.DELETE;
|
|
||||||
import javax.ws.rs.GET;
|
|
||||||
import javax.ws.rs.HeaderParam;
|
|
||||||
import javax.ws.rs.POST;
|
|
||||||
import javax.ws.rs.PUT;
|
|
||||||
import javax.ws.rs.Path;
|
|
||||||
import javax.ws.rs.PathParam;
|
|
||||||
import javax.ws.rs.Produces;
|
|
||||||
import javax.ws.rs.core.Context;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
import javax.ws.rs.core.Response.ResponseBuilder;
|
|
||||||
import javax.ws.rs.core.UriInfo;
|
|
||||||
|
|
||||||
import org.mifosplatform.infrastructure.core.api.ApiConstants;
|
|
||||||
import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper;
|
import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper;
|
||||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||||
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
||||||
import org.mifosplatform.infrastructure.core.serialization.ToApiJsonSerializer;
|
import org.mifosplatform.infrastructure.core.serialization.ToApiJsonSerializer;
|
||||||
import org.mifosplatform.infrastructure.core.service.FileUtils;
|
|
||||||
import org.mifosplatform.infrastructure.documentmanagement.command.DocumentCommand;
|
import org.mifosplatform.infrastructure.documentmanagement.command.DocumentCommand;
|
||||||
import org.mifosplatform.infrastructure.documentmanagement.data.DocumentData;
|
import org.mifosplatform.infrastructure.documentmanagement.data.DocumentData;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.data.FileData;
|
||||||
import org.mifosplatform.infrastructure.documentmanagement.service.DocumentReadPlatformService;
|
import org.mifosplatform.infrastructure.documentmanagement.service.DocumentReadPlatformService;
|
||||||
import org.mifosplatform.infrastructure.documentmanagement.service.DocumentWritePlatformService;
|
import org.mifosplatform.infrastructure.documentmanagement.service.DocumentWritePlatformService;
|
||||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||||
@@ -42,9 +22,17 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.sun.jersey.core.header.FormDataContentDisposition;
|
import javax.ws.rs.*;
|
||||||
import com.sun.jersey.multipart.FormDataBodyPart;
|
import javax.ws.rs.core.Context;
|
||||||
import com.sun.jersey.multipart.FormDataParam;
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.core.Response.ResponseBuilder;
|
||||||
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
@Path("{entityType}/{entityId}/documents")
|
@Path("{entityType}/{entityId}/documents")
|
||||||
@Component
|
@Component
|
||||||
@@ -64,8 +52,8 @@ public class DocumentManagementApiResource {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public DocumentManagementApiResource(final PlatformSecurityContext context,
|
public DocumentManagementApiResource(final PlatformSecurityContext context,
|
||||||
final DocumentReadPlatformService documentReadPlatformService, final DocumentWritePlatformService documentWritePlatformService,
|
final DocumentReadPlatformService documentReadPlatformService, final DocumentWritePlatformService documentWritePlatformService,
|
||||||
final ApiRequestParameterHelper apiRequestParameterHelper, final ToApiJsonSerializer<DocumentData> toApiJsonSerializer) {
|
final ApiRequestParameterHelper apiRequestParameterHelper, final ToApiJsonSerializer<DocumentData> toApiJsonSerializer) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.documentReadPlatformService = documentReadPlatformService;
|
this.documentReadPlatformService = documentReadPlatformService;
|
||||||
this.documentWritePlatformService = documentWritePlatformService;
|
this.documentWritePlatformService = documentWritePlatformService;
|
||||||
@@ -95,8 +83,6 @@ public class DocumentManagementApiResource {
|
|||||||
@FormDataParam("file") final FormDataContentDisposition fileDetails, @FormDataParam("file") final FormDataBodyPart bodyPart,
|
@FormDataParam("file") final FormDataContentDisposition fileDetails, @FormDataParam("file") final FormDataBodyPart bodyPart,
|
||||||
@FormDataParam("name") final String name, @FormDataParam("description") final String description) {
|
@FormDataParam("name") final String name, @FormDataParam("description") final String description) {
|
||||||
|
|
||||||
FileUtils.validateFileSizeWithinPermissibleRange(fileSize, name, ApiConstants.MAX_FILE_UPLOAD_SIZE_IN_MB);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: also need to have a backup and stop reading from stream after
|
* TODO: also need to have a backup and stop reading from stream after
|
||||||
* max size is reached to protect against malicious clients
|
* max size is reached to protect against malicious clients
|
||||||
@@ -124,8 +110,6 @@ public class DocumentManagementApiResource {
|
|||||||
@FormDataParam("file") final FormDataBodyPart bodyPart, @FormDataParam("name") final String name,
|
@FormDataParam("file") final FormDataBodyPart bodyPart, @FormDataParam("name") final String name,
|
||||||
@FormDataParam("description") final String description) {
|
@FormDataParam("description") final String description) {
|
||||||
|
|
||||||
FileUtils.validateFileSizeWithinPermissibleRange(fileSize, name, ApiConstants.MAX_FILE_UPLOAD_SIZE_IN_MB);
|
|
||||||
|
|
||||||
final Set<String> modifiedParams = new HashSet<String>();
|
final Set<String> modifiedParams = new HashSet<String>();
|
||||||
modifiedParams.add("name");
|
modifiedParams.add("name");
|
||||||
modifiedParams.add("description");
|
modifiedParams.add("description");
|
||||||
@@ -182,11 +166,10 @@ public class DocumentManagementApiResource {
|
|||||||
|
|
||||||
this.context.authenticatedUser().validateHasReadPermission(this.SystemEntityType);
|
this.context.authenticatedUser().validateHasReadPermission(this.SystemEntityType);
|
||||||
|
|
||||||
final DocumentData documentData = this.documentReadPlatformService.retrieveDocument(entityType, entityId, documentId);
|
final FileData fileData = this.documentReadPlatformService.retrieveDocumentAsFile(entityType, entityId, documentId);
|
||||||
final File file = new File(documentData.fileLocation());
|
final ResponseBuilder response = Response.ok(fileData.file());
|
||||||
final ResponseBuilder response = Response.ok(file);
|
response.header("Content-Disposition", "attachment; filename=\"" + fileData.name() + "\"");
|
||||||
response.header("Content-Disposition", "attachment; filename=\"" + documentData.fileName() + "\"");
|
response.header("Content-Type", fileData.contentType());
|
||||||
response.header("Content-Type", documentData.contentType());
|
|
||||||
|
|
||||||
return response.build();
|
return response.build();
|
||||||
}
|
}
|
||||||
|
|||||||
+10
@@ -5,6 +5,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.infrastructure.documentmanagement.command;
|
package org.mifosplatform.infrastructure.documentmanagement.command;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.service.DocumentStoreType;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,6 +26,7 @@ public class DocumentCommand {
|
|||||||
private String location;
|
private String location;
|
||||||
|
|
||||||
private final Set<String> modifiedParameters;
|
private final Set<String> modifiedParameters;
|
||||||
|
private DocumentStoreType storageType;
|
||||||
|
|
||||||
public DocumentCommand(final Set<String> modifiedParameters, final Long id, final String parentEntityType, final Long parentEntityId,
|
public DocumentCommand(final Set<String> modifiedParameters, final Long id, final String parentEntityType, final Long parentEntityId,
|
||||||
final String name, final String fileName, final Long size, final String type, final String description, final String location) {
|
final String name, final String fileName, final Long size, final String type, final String description, final String location) {
|
||||||
@@ -119,4 +122,11 @@ public class DocumentCommand {
|
|||||||
return this.modifiedParameters.contains("location");
|
return this.modifiedParameters.contains("location");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setStorageType(DocumentStoreType storageType) {
|
||||||
|
this.storageType = storageType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStorageType(){
|
||||||
|
return storageType.getValue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+23
-1
@@ -5,6 +5,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.infrastructure.documentmanagement.data;
|
package org.mifosplatform.infrastructure.documentmanagement.data;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.service.DocumentStore;
|
||||||
|
import org.mifosplatform.infrastructure.core.service.DocumentStoreType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immutable data object represent document being managed on platform.
|
* Immutable data object represent document being managed on platform.
|
||||||
*/
|
*/
|
||||||
@@ -26,8 +29,10 @@ public class DocumentData {
|
|||||||
private final String description;
|
private final String description;
|
||||||
private String location;
|
private String location;
|
||||||
|
|
||||||
|
private String storageType;
|
||||||
|
|
||||||
public DocumentData(final Long id, final String parentEntityType, final Long parentEntityId, final String name, final String fileName,
|
public DocumentData(final Long id, final String parentEntityType, final Long parentEntityId, final String name, final String fileName,
|
||||||
final Long size, final String type, final String description, final String location) {
|
final Long size, final String type, final String description, final String location, String storageType) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.parentEntityType = parentEntityType;
|
this.parentEntityType = parentEntityType;
|
||||||
this.parentEntityId = parentEntityId;
|
this.parentEntityId = parentEntityId;
|
||||||
@@ -37,6 +42,7 @@ public class DocumentData {
|
|||||||
this.type = type;
|
this.type = type;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.location = location;
|
this.location = location;
|
||||||
|
this.storageType = storageType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String contentType() {
|
public String contentType() {
|
||||||
@@ -55,4 +61,20 @@ public class DocumentData {
|
|||||||
this.location = location;
|
this.location = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DocumentStoreType storeType(){
|
||||||
|
return DocumentStore.getDocumentStoreType(storageType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParentEntityType(){
|
||||||
|
return this.parentEntityType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getParentEntityId(){
|
||||||
|
return this.parentEntityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId(){
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
package org.mifosplatform.infrastructure.documentmanagement.data;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class FileData {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(FileData.class);
|
||||||
|
|
||||||
|
private final File file;
|
||||||
|
private final String fileName;
|
||||||
|
private final String contentType;
|
||||||
|
private final InputStream inputStream;
|
||||||
|
|
||||||
|
public FileData(File file, String fileName, String contentType) {
|
||||||
|
this.file = file;
|
||||||
|
this.fileName = fileName;
|
||||||
|
this.contentType = contentType;
|
||||||
|
this.inputStream = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileData(InputStream inputStream, String fileName, String contentType) {
|
||||||
|
this.file = null;
|
||||||
|
this.inputStream = inputStream;
|
||||||
|
this.fileName = fileName;
|
||||||
|
this.contentType = contentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String contentType() {
|
||||||
|
return contentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String name() {
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream file(){
|
||||||
|
try{
|
||||||
|
if(inputStream == null){
|
||||||
|
return new FileInputStream(file);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return inputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (FileNotFoundException e){
|
||||||
|
logger.error(e.toString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+19
-9
@@ -5,14 +5,16 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.infrastructure.documentmanagement.domain;
|
package org.mifosplatform.infrastructure.documentmanagement.domain;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.mifosplatform.infrastructure.core.service.DocumentStore;
|
||||||
|
import org.mifosplatform.infrastructure.core.service.DocumentStoreType;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.command.DocumentCommand;
|
||||||
|
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.mifosplatform.infrastructure.documentmanagement.command.DocumentCommand;
|
|
||||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "m_document")
|
@Table(name = "m_document")
|
||||||
public class Document extends AbstractPersistable<Long> {
|
public class Document extends AbstractPersistable<Long> {
|
||||||
@@ -41,15 +43,19 @@ public class Document extends AbstractPersistable<Long> {
|
|||||||
@Column(name = "location", length = 500)
|
@Column(name = "location", length = 500)
|
||||||
private String location;
|
private String location;
|
||||||
|
|
||||||
public Document() {}
|
@Column(name = "storage_type", length = 50)
|
||||||
|
private String storageType;
|
||||||
|
|
||||||
|
public Document() {
|
||||||
|
}
|
||||||
|
|
||||||
public static Document createNew(final String parentEntityType, final Long parentEntityId, final String name, final String fileName,
|
public static Document createNew(final String parentEntityType, final Long parentEntityId, final String name, final String fileName,
|
||||||
final Long size, final String type, final String description, final String location) {
|
final Long size, final String type, final String description, final String location, final DocumentStoreType storageType) {
|
||||||
return new Document(parentEntityType, parentEntityId, name, fileName, size, type, description, location);
|
return new Document(parentEntityType, parentEntityId, name, fileName, size, type, description, location, storageType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Document(final String parentEntityType, final Long parentEntityId, final String name, final String fileName, final Long size,
|
private Document(final String parentEntityType, final Long parentEntityId, final String name, final String fileName, final Long size,
|
||||||
final String type, final String description, final String location) {
|
final String type, final String description, final String location, final DocumentStoreType storageType) {
|
||||||
this.parentEntityType = StringUtils.defaultIfEmpty(parentEntityType, null);
|
this.parentEntityType = StringUtils.defaultIfEmpty(parentEntityType, null);
|
||||||
this.parentEntityId = parentEntityId;
|
this.parentEntityId = parentEntityId;
|
||||||
this.name = StringUtils.defaultIfEmpty(name, null);
|
this.name = StringUtils.defaultIfEmpty(name, null);
|
||||||
@@ -58,6 +64,7 @@ public class Document extends AbstractPersistable<Long> {
|
|||||||
this.type = StringUtils.defaultIfEmpty(type, null);
|
this.type = StringUtils.defaultIfEmpty(type, null);
|
||||||
this.description = StringUtils.defaultIfEmpty(description, null);
|
this.description = StringUtils.defaultIfEmpty(description, null);
|
||||||
this.location = StringUtils.defaultIfEmpty(location, null);
|
this.location = StringUtils.defaultIfEmpty(location, null);
|
||||||
|
this.storageType = storageType.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(final DocumentCommand command) {
|
public void update(final DocumentCommand command) {
|
||||||
@@ -79,7 +86,7 @@ public class Document extends AbstractPersistable<Long> {
|
|||||||
if (command.isSizeChanged()) {
|
if (command.isSizeChanged()) {
|
||||||
this.size = command.getSize();
|
this.size = command.getSize();
|
||||||
}
|
}
|
||||||
|
this.storageType = command.getStorageType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getParentEntityType() {
|
public String getParentEntityType() {
|
||||||
@@ -146,4 +153,7 @@ public class Document extends AbstractPersistable<Long> {
|
|||||||
this.location = location;
|
this.location = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DocumentStoreType storageType(){
|
||||||
|
return DocumentStore.getDocumentStoreType(this.storageType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+6
-2
@@ -5,13 +5,17 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.infrastructure.documentmanagement.service;
|
package org.mifosplatform.infrastructure.documentmanagement.service;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import org.mifosplatform.infrastructure.documentmanagement.data.DocumentData;
|
import org.mifosplatform.infrastructure.documentmanagement.data.DocumentData;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.data.FileData;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
public interface DocumentReadPlatformService {
|
public interface DocumentReadPlatformService {
|
||||||
|
|
||||||
Collection<DocumentData> retrieveAllDocuments(String entityType, Long entityId);
|
Collection<DocumentData> retrieveAllDocuments(String entityType, Long entityId);
|
||||||
|
|
||||||
|
FileData retrieveDocumentAsFile(String entityType, Long entityId, Long documentId);
|
||||||
|
|
||||||
DocumentData retrieveDocument(String entityType, Long entityId, Long documentId);
|
DocumentData retrieveDocument(String entityType, Long entityId, Long documentId);
|
||||||
|
|
||||||
}
|
}
|
||||||
+41
-16
@@ -5,13 +5,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.infrastructure.documentmanagement.service;
|
package org.mifosplatform.infrastructure.documentmanagement.service;
|
||||||
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||||
|
import org.mifosplatform.infrastructure.core.service.DocumentStore;
|
||||||
|
import org.mifosplatform.infrastructure.core.service.DocumentStoreFactory;
|
||||||
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
|
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
|
||||||
import org.mifosplatform.infrastructure.documentmanagement.data.DocumentData;
|
import org.mifosplatform.infrastructure.documentmanagement.data.DocumentData;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.data.FileData;
|
||||||
import org.mifosplatform.infrastructure.documentmanagement.exception.DocumentNotFoundException;
|
import org.mifosplatform.infrastructure.documentmanagement.exception.DocumentNotFoundException;
|
||||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -20,16 +19,23 @@ import org.springframework.jdbc.core.JdbcTemplate;
|
|||||||
import org.springframework.jdbc.core.RowMapper;
|
import org.springframework.jdbc.core.RowMapper;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class DocumentReadPlatformServiceImpl implements DocumentReadPlatformService {
|
public class DocumentReadPlatformServiceImpl implements DocumentReadPlatformService {
|
||||||
|
|
||||||
private final JdbcTemplate jdbcTemplate;
|
private final JdbcTemplate jdbcTemplate;
|
||||||
private final PlatformSecurityContext context;
|
private final PlatformSecurityContext context;
|
||||||
|
private final DocumentStoreFactory documentStoreFactory;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public DocumentReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource) {
|
public DocumentReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource,
|
||||||
|
final DocumentStoreFactory documentStoreFactory) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||||
|
this.documentStoreFactory = documentStoreFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -46,17 +52,22 @@ public class DocumentReadPlatformServiceImpl implements DocumentReadPlatformServ
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DocumentData retrieveDocument(final String entityType, final Long entityId, final Long documentId) {
|
public FileData retrieveDocumentAsFile(final String entityType, final Long entityId, final Long documentId) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.context.authenticatedUser();
|
DocumentData documentData = getDocumentData(entityType, entityId, documentId);
|
||||||
|
DocumentStore instanceForRead = documentStoreFactory.getInstanceFromStorageType(documentData.storeType());
|
||||||
|
return instanceForRead.retrieveDocument(documentData);
|
||||||
|
} catch (final EmptyResultDataAccessException e) {
|
||||||
|
throw new DocumentNotFoundException(entityType, entityId, documentId);
|
||||||
|
} catch (final DocumentNotFoundException d) {
|
||||||
|
throw d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO verify if the entities are valid and a
|
@Override
|
||||||
// user has data
|
public DocumentData retrieveDocument(String entityType, Long entityId, Long documentId) {
|
||||||
// scope for the particular entities
|
try {
|
||||||
final DocumentMapper mapper = new DocumentMapper(false);
|
return getDocumentData(entityType, entityId, documentId);
|
||||||
final String sql = "select " + mapper.schema() + " and d.id=? ";
|
|
||||||
return this.jdbcTemplate.queryForObject(sql, mapper, new Object[] { entityType, entityId, documentId });
|
|
||||||
} catch (final EmptyResultDataAccessException e) {
|
} catch (final EmptyResultDataAccessException e) {
|
||||||
throw new DocumentNotFoundException(entityType, entityId, documentId);
|
throw new DocumentNotFoundException(entityType, entityId, documentId);
|
||||||
}
|
}
|
||||||
@@ -73,7 +84,8 @@ public class DocumentReadPlatformServiceImpl implements DocumentReadPlatformServ
|
|||||||
public String schema() {
|
public String schema() {
|
||||||
return "d.id as id, d.parent_entity_type as parentEntityType, d.parent_entity_id as parentEntityId, d.name as name, "
|
return "d.id as id, d.parent_entity_type as parentEntityType, d.parent_entity_id as parentEntityId, d.name as name, "
|
||||||
+ " d.file_name as fileName, d.size as fileSize, d.type as fileType, "
|
+ " d.file_name as fileName, d.size as fileSize, d.type as fileType, "
|
||||||
+ " d.description as description, d.location as location"
|
+ " d.description as description, d.location as location,"
|
||||||
|
+ " d.storage_type as storageType"
|
||||||
+ " from m_document d where d.parent_entity_type=? and d.parent_entity_id=?";
|
+ " from m_document d where d.parent_entity_type=? and d.parent_entity_id=?";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,8 +104,21 @@ public class DocumentReadPlatformServiceImpl implements DocumentReadPlatformServ
|
|||||||
if (!this.hideLocation) {
|
if (!this.hideLocation) {
|
||||||
location = rs.getString("location");
|
location = rs.getString("location");
|
||||||
}
|
}
|
||||||
|
final String storageType = rs.getString("storageType");
|
||||||
|
|
||||||
return new DocumentData(id, parentEntityType, parentEntityId, name, fileName, fileSize, fileType, description, location);
|
return new DocumentData(id, parentEntityType, parentEntityId, name, fileName, fileSize, fileType, description, location, storageType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private DocumentData getDocumentData(String entityType, Long entityId, Long documentId) {
|
||||||
|
this.context.authenticatedUser();
|
||||||
|
|
||||||
|
// TODO verify if the entities are valid and a
|
||||||
|
// user has data
|
||||||
|
// scope for the particular entities
|
||||||
|
final DocumentMapper mapper = new DocumentMapper(false);
|
||||||
|
final String sql = "select " + mapper.schema() + " and d.id=? ";
|
||||||
|
return this.jdbcTemplate.queryForObject(sql, mapper, new Object[]{entityType, entityId, documentId});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+24
-41
@@ -5,13 +5,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.infrastructure.documentmanagement.service;
|
package org.mifosplatform.infrastructure.documentmanagement.service;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||||
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||||
import org.mifosplatform.infrastructure.core.service.FileUtils;
|
import org.mifosplatform.infrastructure.core.service.DocumentStore;
|
||||||
|
import org.mifosplatform.infrastructure.core.service.DocumentStoreFactory;
|
||||||
|
import org.mifosplatform.infrastructure.core.service.DocumentStoreType;
|
||||||
import org.mifosplatform.infrastructure.documentmanagement.command.DocumentCommand;
|
import org.mifosplatform.infrastructure.documentmanagement.command.DocumentCommand;
|
||||||
import org.mifosplatform.infrastructure.documentmanagement.command.DocumentCommandValidator;
|
import org.mifosplatform.infrastructure.documentmanagement.command.DocumentCommandValidator;
|
||||||
import org.mifosplatform.infrastructure.documentmanagement.domain.Document;
|
import org.mifosplatform.infrastructure.documentmanagement.domain.Document;
|
||||||
@@ -27,6 +25,8 @@ import org.springframework.dao.DataIntegrityViolationException;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class DocumentWritePlatformServiceJpaRepositoryImpl implements DocumentWritePlatformService {
|
public class DocumentWritePlatformServiceJpaRepositoryImpl implements DocumentWritePlatformService {
|
||||||
|
|
||||||
@@ -34,11 +34,14 @@ public class DocumentWritePlatformServiceJpaRepositoryImpl implements DocumentWr
|
|||||||
|
|
||||||
private final PlatformSecurityContext context;
|
private final PlatformSecurityContext context;
|
||||||
private final DocumentRepository documentRepository;
|
private final DocumentRepository documentRepository;
|
||||||
|
private final DocumentStoreFactory documentStoreFactory;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public DocumentWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final DocumentRepository documentRepository) {
|
public DocumentWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final DocumentRepository documentRepository,
|
||||||
|
final DocumentStoreFactory documentStoreFactory) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.documentRepository = documentRepository;
|
this.documentRepository = documentRepository;
|
||||||
|
this.documentStoreFactory = documentStoreFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@@ -53,19 +56,13 @@ public class DocumentWritePlatformServiceJpaRepositoryImpl implements DocumentWr
|
|||||||
|
|
||||||
validator.validateForCreate();
|
validator.validateForCreate();
|
||||||
|
|
||||||
final String fileUploadLocation = FileUtils.generateFileParentDirectory(documentCommand.getParentEntityType(),
|
DocumentStore documentStore = this.documentStoreFactory.getInstanceFromConfiguration();
|
||||||
documentCommand.getParentEntityId());
|
|
||||||
|
|
||||||
/** Recursively create the directory if it does not exist **/
|
final String fileLocation = documentStore.saveDocument(inputStream, documentCommand);
|
||||||
if (!new File(fileUploadLocation).isDirectory()) {
|
|
||||||
new File(fileUploadLocation).mkdirs();
|
|
||||||
}
|
|
||||||
|
|
||||||
final String fileLocation = FileUtils.saveToFileSystem(inputStream, fileUploadLocation, documentCommand.getFileName());
|
|
||||||
|
|
||||||
final Document document = Document.createNew(documentCommand.getParentEntityType(), documentCommand.getParentEntityId(),
|
final Document document = Document.createNew(documentCommand.getParentEntityType(), documentCommand.getParentEntityId(),
|
||||||
documentCommand.getName(), documentCommand.getFileName(), documentCommand.getSize(), documentCommand.getType(),
|
documentCommand.getName(), documentCommand.getFileName(), documentCommand.getSize(), documentCommand.getType(),
|
||||||
documentCommand.getDescription(), fileLocation);
|
documentCommand.getDescription(), fileLocation, documentStore.getType());
|
||||||
|
|
||||||
this.documentRepository.save(document);
|
this.documentRepository.save(document);
|
||||||
|
|
||||||
@@ -74,8 +71,8 @@ public class DocumentWritePlatformServiceJpaRepositoryImpl implements DocumentWr
|
|||||||
logger.error(dve.getMessage(), dve);
|
logger.error(dve.getMessage(), dve);
|
||||||
throw new PlatformDataIntegrityException("error.msg.document.unknown.data.integrity.issue",
|
throw new PlatformDataIntegrityException("error.msg.document.unknown.data.integrity.issue",
|
||||||
"Unknown data integrity issue with resource.");
|
"Unknown data integrity issue with resource.");
|
||||||
} catch (final IOException ioe) {
|
} catch (final DocumentManagementException dme) {
|
||||||
logger.error(ioe.getMessage(), ioe);
|
logger.error(dme.getMessage(), dme);
|
||||||
throw new DocumentManagementException(documentCommand.getName());
|
throw new DocumentManagementException(documentCommand.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,30 +89,21 @@ public class DocumentWritePlatformServiceJpaRepositoryImpl implements DocumentWr
|
|||||||
// TODO check if entity id is valid and within data scope for the
|
// TODO check if entity id is valid and within data scope for the
|
||||||
// user
|
// user
|
||||||
final Document documentForUpdate = this.documentRepository.findOne(documentCommand.getId());
|
final Document documentForUpdate = this.documentRepository.findOne(documentCommand.getId());
|
||||||
|
DocumentStoreType documentStoreType = documentForUpdate.storageType();
|
||||||
if (documentForUpdate == null) { throw new DocumentNotFoundException(documentCommand.getParentEntityType(),
|
if (documentForUpdate == null) { throw new DocumentNotFoundException(documentCommand.getParentEntityType(),
|
||||||
documentCommand.getParentEntityId(), documentCommand.getId()); }
|
documentCommand.getParentEntityId(), documentCommand.getId()); }
|
||||||
oldLocation = documentForUpdate.getLocation();
|
oldLocation = documentForUpdate.getLocation();
|
||||||
// if a new file is also passed in
|
|
||||||
if (inputStream != null && documentCommand.isFileNameChanged()) {
|
if (inputStream != null && documentCommand.isFileNameChanged()) {
|
||||||
final String fileUploadLocation = FileUtils.generateFileParentDirectory(documentCommand.getParentEntityType(),
|
DocumentStore instanceFromConfiguration = this.documentStoreFactory.getInstanceFromConfiguration();
|
||||||
documentCommand.getParentEntityId());
|
documentCommand.setLocation(instanceFromConfiguration.saveDocument(inputStream, documentCommand));
|
||||||
|
documentCommand.setStorageType(instanceFromConfiguration.getType());
|
||||||
/** Recursively create the directory if it does not exist **/
|
|
||||||
if (!new File(fileUploadLocation).isDirectory()) {
|
|
||||||
new File(fileUploadLocation).mkdirs();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO provide switch to toggle between file system appender
|
|
||||||
// and Amazon S3 appender
|
|
||||||
final String fileLocation = FileUtils.saveToFileSystem(inputStream, fileUploadLocation, documentCommand.getFileName());
|
|
||||||
documentCommand.setLocation(fileLocation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
documentForUpdate.update(documentCommand);
|
documentForUpdate.update(documentCommand);
|
||||||
|
|
||||||
if (inputStream != null && documentCommand.isFileNameChanged()) {
|
if (inputStream != null && documentCommand.isFileNameChanged()) {
|
||||||
// delete previous file
|
DocumentStore documentStore = this.documentStoreFactory.getInstanceFromStorageType(documentStoreType);
|
||||||
deleteFile(documentCommand.getName(), oldLocation);
|
documentStore.deleteDocument(documentCommand.getName(), oldLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.documentRepository.saveAndFlush(documentForUpdate);
|
this.documentRepository.saveAndFlush(documentForUpdate);
|
||||||
@@ -125,8 +113,8 @@ public class DocumentWritePlatformServiceJpaRepositoryImpl implements DocumentWr
|
|||||||
logger.error(dve.getMessage(), dve);
|
logger.error(dve.getMessage(), dve);
|
||||||
throw new PlatformDataIntegrityException("error.msg.document.unknown.data.integrity.issue",
|
throw new PlatformDataIntegrityException("error.msg.document.unknown.data.integrity.issue",
|
||||||
"Unknown data integrity issue with resource.");
|
"Unknown data integrity issue with resource.");
|
||||||
} catch (final IOException ioe) {
|
} catch (final DocumentManagementException dme) {
|
||||||
logger.error(ioe.getMessage(), ioe);
|
logger.error(dme.getMessage(), dme);
|
||||||
throw new DocumentManagementException(documentCommand.getName());
|
throw new DocumentManagementException(documentCommand.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,20 +127,15 @@ public class DocumentWritePlatformServiceJpaRepositoryImpl implements DocumentWr
|
|||||||
validateParentEntityType(documentCommand);
|
validateParentEntityType(documentCommand);
|
||||||
// TODO: Check document is present under this entity Id
|
// TODO: Check document is present under this entity Id
|
||||||
final Document document = this.documentRepository.findOne(documentCommand.getId());
|
final Document document = this.documentRepository.findOne(documentCommand.getId());
|
||||||
|
DocumentStore documentStore = this.documentStoreFactory.getInstanceFromStorageType(document.storageType());
|
||||||
if (document == null) { throw new DocumentNotFoundException(documentCommand.getParentEntityType(),
|
if (document == null) { throw new DocumentNotFoundException(documentCommand.getParentEntityType(),
|
||||||
documentCommand.getParentEntityId(), documentCommand.getId()); }
|
documentCommand.getParentEntityId(), documentCommand.getId()); }
|
||||||
|
|
||||||
this.documentRepository.delete(document);
|
this.documentRepository.delete(document);
|
||||||
deleteFile(document.getName(), document.getLocation());
|
documentStore.deleteDocument(document.getName(), document.getLocation());
|
||||||
return new CommandProcessingResult(document.getId());
|
return new CommandProcessingResult(document.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteFile(final String documentName, final String location) {
|
|
||||||
final File fileToBeDeleted = new File(location);
|
|
||||||
final boolean fileDeleted = fileToBeDeleted.delete();
|
|
||||||
if (!fileDeleted) { throw new DocumentManagementException(documentName); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private void validateParentEntityType(final DocumentCommand documentCommand) {
|
private void validateParentEntityType(final DocumentCommand documentCommand) {
|
||||||
if (!checkValidEntityType(documentCommand.getParentEntityType())) { throw new InvalidEntityTypeForDocumentManagementException(
|
if (!checkValidEntityType(documentCommand.getParentEntityType())) { throw new InvalidEntityTypeForDocumentManagementException(
|
||||||
documentCommand.getParentEntityType()); }
|
documentCommand.getParentEntityType()); }
|
||||||
|
|||||||
+27
-51
@@ -5,44 +5,31 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.client.api;
|
package org.mifosplatform.portfolio.client.api;
|
||||||
|
|
||||||
import java.io.File;
|
import com.lowagie.text.pdf.codec.Base64;
|
||||||
import java.io.InputStream;
|
import com.sun.jersey.core.header.FormDataContentDisposition;
|
||||||
|
import com.sun.jersey.multipart.FormDataBodyPart;
|
||||||
import javax.ws.rs.Consumes;
|
import com.sun.jersey.multipart.FormDataParam;
|
||||||
import javax.ws.rs.DELETE;
|
|
||||||
import javax.ws.rs.GET;
|
|
||||||
import javax.ws.rs.HeaderParam;
|
|
||||||
import javax.ws.rs.POST;
|
|
||||||
import javax.ws.rs.PUT;
|
|
||||||
import javax.ws.rs.Path;
|
|
||||||
import javax.ws.rs.PathParam;
|
|
||||||
import javax.ws.rs.Produces;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
import javax.ws.rs.core.Response.ResponseBuilder;
|
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.mifosplatform.infrastructure.core.api.ApiConstants;
|
|
||||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||||
import org.mifosplatform.infrastructure.core.domain.Base64EncodedImage;
|
import org.mifosplatform.infrastructure.core.domain.Base64EncodedImage;
|
||||||
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||||
import org.mifosplatform.infrastructure.core.service.FileUtils;
|
import org.mifosplatform.infrastructure.core.service.ImageUtils;
|
||||||
import org.mifosplatform.infrastructure.core.service.FileUtils.IMAGE_DATA_URI_SUFFIX;
|
|
||||||
import org.mifosplatform.infrastructure.core.service.FileUtils.IMAGE_FILE_EXTENSION;
|
|
||||||
import org.mifosplatform.infrastructure.core.service.FileUtils.IMAGE_MIME_TYPE;
|
|
||||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||||
import org.mifosplatform.portfolio.client.data.ClientData;
|
import org.mifosplatform.portfolio.client.data.ClientData;
|
||||||
import org.mifosplatform.portfolio.client.exception.ImageNotFoundException;
|
import org.mifosplatform.portfolio.client.exception.ImageNotFoundException;
|
||||||
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
|
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
|
||||||
import org.mifosplatform.portfolio.client.service.ClientWritePlatformService;
|
import org.mifosplatform.portfolio.client.service.ClientWritePlatformService;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.lowagie.text.pdf.codec.Base64;
|
import javax.ws.rs.*;
|
||||||
import com.sun.jersey.core.header.FormDataContentDisposition;
|
import javax.ws.rs.core.MediaType;
|
||||||
import com.sun.jersey.multipart.FormDataBodyPart;
|
import javax.ws.rs.core.Response;
|
||||||
import com.sun.jersey.multipart.FormDataParam;
|
import javax.ws.rs.core.Response.ResponseBuilder;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
@Path("/clients/{clientId}/images")
|
@Path("/clients/{clientId}/images")
|
||||||
@Component
|
@Component
|
||||||
@@ -53,10 +40,11 @@ public class ClientImagesApiResource {
|
|||||||
private final ClientReadPlatformService clientReadPlatformService;
|
private final ClientReadPlatformService clientReadPlatformService;
|
||||||
private final ClientWritePlatformService clientWritePlatformService;
|
private final ClientWritePlatformService clientWritePlatformService;
|
||||||
private final DefaultToApiJsonSerializer<ClientData> toApiJsonSerializer;
|
private final DefaultToApiJsonSerializer<ClientData> toApiJsonSerializer;
|
||||||
|
private final static Logger logger = LoggerFactory.getLogger(ClientImagesApiResource.class);
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public ClientImagesApiResource(final PlatformSecurityContext context, final ClientReadPlatformService readPlatformService,
|
public ClientImagesApiResource(final PlatformSecurityContext context, final ClientReadPlatformService readPlatformService,
|
||||||
final ClientWritePlatformService clientWritePlatformService, final DefaultToApiJsonSerializer<ClientData> toApiJsonSerializer) {
|
final ClientWritePlatformService clientWritePlatformService, final DefaultToApiJsonSerializer<ClientData> toApiJsonSerializer) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.clientReadPlatformService = readPlatformService;
|
this.clientReadPlatformService = readPlatformService;
|
||||||
this.clientWritePlatformService = clientWritePlatformService;
|
this.clientWritePlatformService = clientWritePlatformService;
|
||||||
@@ -76,12 +64,11 @@ public class ClientImagesApiResource {
|
|||||||
// TODO: vishwas might need more advances validation (like reading magic
|
// TODO: vishwas might need more advances validation (like reading magic
|
||||||
// number) for handling malicious clients
|
// number) for handling malicious clients
|
||||||
// and clients not setting mime type
|
// and clients not setting mime type
|
||||||
FileUtils.validateClientImageNotEmpty(fileDetails.getFileName());
|
ImageUtils.validateClientImageNotEmpty(fileDetails.getFileName());
|
||||||
FileUtils.validateImageMimeType(bodyPart.getMediaType().toString());
|
ImageUtils.validateImageMimeType(bodyPart.getMediaType().toString());
|
||||||
FileUtils.validateFileSizeWithinPermissibleRange(fileSize, fileDetails.getFileName(), ApiConstants.MAX_FILE_UPLOAD_SIZE_IN_MB);
|
|
||||||
|
|
||||||
final CommandProcessingResult result = this.clientWritePlatformService.saveOrUpdateClientImage(clientId, fileDetails.getFileName(),
|
final CommandProcessingResult result = this.clientWritePlatformService.saveOrUpdateClientImage(clientId, fileDetails.getFileName(),
|
||||||
inputStream);
|
inputStream, fileSize);
|
||||||
|
|
||||||
return this.toApiJsonSerializer.serialize(result);
|
return this.toApiJsonSerializer.serialize(result);
|
||||||
}
|
}
|
||||||
@@ -94,7 +81,7 @@ public class ClientImagesApiResource {
|
|||||||
@Produces({ MediaType.APPLICATION_JSON })
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
public String addNewClientImage(@PathParam("clientId") final Long clientId, final String jsonRequestBody) {
|
public String addNewClientImage(@PathParam("clientId") final Long clientId, final String jsonRequestBody) {
|
||||||
|
|
||||||
final Base64EncodedImage base64EncodedImage = FileUtils.extractImageFromDataURL(jsonRequestBody);
|
final Base64EncodedImage base64EncodedImage = ImageUtils.extractImageFromDataURL(jsonRequestBody);
|
||||||
|
|
||||||
final CommandProcessingResult result = this.clientWritePlatformService.saveOrUpdateClientImage(clientId, base64EncodedImage);
|
final CommandProcessingResult result = this.clientWritePlatformService.saveOrUpdateClientImage(clientId, base64EncodedImage);
|
||||||
|
|
||||||
@@ -116,15 +103,14 @@ public class ClientImagesApiResource {
|
|||||||
if (clientData.imageKeyDoesNotExist()) { throw new ImageNotFoundException("clients", clientId); }
|
if (clientData.imageKeyDoesNotExist()) { throw new ImageNotFoundException("clients", clientId); }
|
||||||
|
|
||||||
// TODO: Need a better way of determining image type
|
// TODO: Need a better way of determining image type
|
||||||
String imageDataURISuffix = IMAGE_DATA_URI_SUFFIX.JPEG.getValue();
|
String imageDataURISuffix = ImageUtils.IMAGE_DATA_URI_SUFFIX.JPEG.getValue();
|
||||||
if (StringUtils.endsWith(clientData.imageKey(), IMAGE_FILE_EXTENSION.GIF.getValue())) {
|
if (StringUtils.endsWith(clientData.imageKey(), ImageUtils.IMAGE_FILE_EXTENSION.GIF.getValue())) {
|
||||||
imageDataURISuffix = IMAGE_DATA_URI_SUFFIX.GIF.getValue();
|
imageDataURISuffix = ImageUtils.IMAGE_DATA_URI_SUFFIX.GIF.getValue();
|
||||||
} else if (StringUtils.endsWith(clientData.imageKey(), IMAGE_FILE_EXTENSION.PNG.getValue())) {
|
} else if (StringUtils.endsWith(clientData.imageKey(), ImageUtils.IMAGE_FILE_EXTENSION.PNG.getValue())) {
|
||||||
imageDataURISuffix = IMAGE_DATA_URI_SUFFIX.PNG.getValue();
|
imageDataURISuffix = ImageUtils.IMAGE_DATA_URI_SUFFIX.PNG.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
String clientImageAsBase64Text = imageDataURISuffix + Base64.encodeFromFile(clientData.imageKey());
|
String clientImageAsBase64Text = imageDataURISuffix + Base64.encodeBytes(clientData.image());
|
||||||
|
|
||||||
return clientImageAsBase64Text;
|
return clientImageAsBase64Text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,22 +124,12 @@ public class ClientImagesApiResource {
|
|||||||
|
|
||||||
if (clientData.imageKeyDoesNotExist()) { throw new ImageNotFoundException("clients", clientId); }
|
if (clientData.imageKeyDoesNotExist()) { throw new ImageNotFoundException("clients", clientId); }
|
||||||
|
|
||||||
File image = new File(clientData.imageKey());
|
ResponseBuilder response = Response.ok(clientData.image());
|
||||||
String imageName = image.getName();
|
response.header("Content-Disposition", "attachment; filename=\"" + clientData.imageName() + "\"");
|
||||||
ResponseBuilder response = Response.ok(image);
|
|
||||||
response.header("Content-Disposition", "attachment; filename=\"" + imageName + "\"");
|
|
||||||
|
|
||||||
// TODO: Need a better way of determining image type
|
// TODO: Need a better way of determining image type
|
||||||
|
|
||||||
// determine image type
|
response.header("Content-Type", clientData.imageContentType());
|
||||||
String contentType = IMAGE_MIME_TYPE.JPEG.getValue();
|
|
||||||
if (StringUtils.endsWith(imageName, IMAGE_FILE_EXTENSION.GIF.getValue())) {
|
|
||||||
contentType = IMAGE_MIME_TYPE.GIF.getValue();
|
|
||||||
} else if (StringUtils.endsWith(imageName, IMAGE_FILE_EXTENSION.PNG.getValue())) {
|
|
||||||
contentType = IMAGE_MIME_TYPE.PNG.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
response.header("Content-Type", contentType);
|
|
||||||
return response.build();
|
return response.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+41
-14
@@ -5,9 +5,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.client.data;
|
package org.mifosplatform.portfolio.client.data;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.commons.lang.builder.CompareToBuilder;
|
import org.apache.commons.lang.builder.CompareToBuilder;
|
||||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||||
@@ -16,12 +13,21 @@ import org.joda.time.LocalDate;
|
|||||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||||
import org.mifosplatform.organisation.office.data.OfficeData;
|
import org.mifosplatform.organisation.office.data.OfficeData;
|
||||||
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
|
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immutable data object representing client data.
|
* Immutable data object representing client data.
|
||||||
*/
|
*/
|
||||||
final public class ClientData implements Comparable<ClientData> {
|
final public class ClientData implements Comparable<ClientData> {
|
||||||
|
|
||||||
|
private final static Logger logger = LoggerFactory.getLogger(ClientData.class);
|
||||||
|
|
||||||
|
|
||||||
private final Long id;
|
private final Long id;
|
||||||
private final String accountNo;
|
private final String accountNo;
|
||||||
private final String externalId;
|
private final String externalId;
|
||||||
@@ -40,7 +46,8 @@ final public class ClientData implements Comparable<ClientData> {
|
|||||||
private final Long officeId;
|
private final Long officeId;
|
||||||
private final String officeName;
|
private final String officeName;
|
||||||
|
|
||||||
private final String imageKey;
|
// private String imageData;
|
||||||
|
private ImageData imageData;
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private final Boolean imagePresent;
|
private final Boolean imagePresent;
|
||||||
|
|
||||||
@@ -58,13 +65,13 @@ final public class ClientData implements Comparable<ClientData> {
|
|||||||
|
|
||||||
return new ClientData(clientData.accountNo, clientData.status, clientData.officeId, clientData.officeName, clientData.id,
|
return new ClientData(clientData.accountNo, clientData.status, clientData.officeId, clientData.officeName, clientData.id,
|
||||||
clientData.firstname, clientData.middlename, clientData.lastname, clientData.fullname, clientData.displayName,
|
clientData.firstname, clientData.middlename, clientData.lastname, clientData.fullname, clientData.displayName,
|
||||||
clientData.externalId, clientData.activationDate, clientData.imageKey, allowedOffices, clientData.groups);
|
clientData.externalId, clientData.activationDate, clientData.imageData, allowedOffices, clientData.groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ClientData setParentGroups(final ClientData clientData, final Collection<GroupGeneralData> parentGroups) {
|
public static ClientData setParentGroups(final ClientData clientData, final Collection<GroupGeneralData> parentGroups) {
|
||||||
return new ClientData(clientData.accountNo, clientData.status, clientData.officeId, clientData.officeName, clientData.id,
|
return new ClientData(clientData.accountNo, clientData.status, clientData.officeId, clientData.officeName, clientData.id,
|
||||||
clientData.firstname, clientData.middlename, clientData.lastname, clientData.fullname, clientData.displayName,
|
clientData.firstname, clientData.middlename, clientData.lastname, clientData.fullname, clientData.displayName,
|
||||||
clientData.externalId, clientData.activationDate, clientData.imageKey, clientData.officeOptions, parentGroups);
|
clientData.externalId, clientData.activationDate, clientData.imageData, clientData.officeOptions, parentGroups);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ClientData clientIdentifier(final Long id, final String accountNo, final EnumOptionData status, final String firstname,
|
public static ClientData clientIdentifier(final Long id, final String accountNo, final EnumOptionData status, final String firstname,
|
||||||
@@ -81,14 +88,14 @@ final public class ClientData implements Comparable<ClientData> {
|
|||||||
|
|
||||||
public static ClientData instance(final String accountNo, final EnumOptionData status, final Long officeId, final String officeName,
|
public static ClientData instance(final String accountNo, final EnumOptionData status, final Long officeId, final String officeName,
|
||||||
final Long id, final String firstname, final String middlename, final String lastname, final String fullname,
|
final Long id, final String firstname, final String middlename, final String lastname, final String fullname,
|
||||||
final String displayName, final String externalId, final LocalDate activationDate, final String imageKey) {
|
final String displayName, final String externalId, final LocalDate activationDate, final ImageData imageData) {
|
||||||
return new ClientData(accountNo, status, officeId, officeName, id, firstname, middlename, lastname, fullname, displayName,
|
return new ClientData(accountNo, status, officeId, officeName, id, firstname, middlename, lastname, fullname, displayName,
|
||||||
externalId, activationDate, imageKey, null, null);
|
externalId, activationDate, imageData, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClientData(final String accountNo, final EnumOptionData status, final Long officeId, final String officeName, final Long id,
|
private ClientData(final String accountNo, final EnumOptionData status, final Long officeId, final String officeName, final Long id,
|
||||||
final String firstname, final String middlename, final String lastname, final String fullname, final String displayName,
|
final String firstname, final String middlename, final String lastname, final String fullname, final String displayName,
|
||||||
final String externalId, final LocalDate activationDate, final String imageKey, final Collection<OfficeData> allowedOffices,
|
final String externalId, final LocalDate activationDate, final ImageData imageKey, final Collection<OfficeData> allowedOffices,
|
||||||
final Collection<GroupGeneralData> groups) {
|
final Collection<GroupGeneralData> groups) {
|
||||||
this.accountNo = accountNo;
|
this.accountNo = accountNo;
|
||||||
this.status = status;
|
this.status = status;
|
||||||
@@ -107,7 +114,7 @@ final public class ClientData implements Comparable<ClientData> {
|
|||||||
this.displayName = StringUtils.defaultIfEmpty(displayName, null);
|
this.displayName = StringUtils.defaultIfEmpty(displayName, null);
|
||||||
this.externalId = StringUtils.defaultIfEmpty(externalId, null);
|
this.externalId = StringUtils.defaultIfEmpty(externalId, null);
|
||||||
this.activationDate = activationDate;
|
this.activationDate = activationDate;
|
||||||
this.imageKey = imageKey;
|
this.imageData = imageKey;
|
||||||
if (imageKey != null) {
|
if (imageKey != null) {
|
||||||
this.imagePresent = Boolean.TRUE;
|
this.imagePresent = Boolean.TRUE;
|
||||||
} else {
|
} else {
|
||||||
@@ -138,17 +145,16 @@ final public class ClientData implements Comparable<ClientData> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String imageKey() {
|
public String imageKey() {
|
||||||
return this.imageKey;
|
return this.imageData.imageKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean imageKeyDoesNotExist() {
|
public boolean imageKeyDoesNotExist() {
|
||||||
return !imageKeyExists();
|
return imageData.equals(null) && !imageKeyExists();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean imageKeyExists() {
|
private boolean imageKeyExists() {
|
||||||
return StringUtils.isNotBlank(this.imageKey);
|
return StringUtils.isNotBlank(this.imageData.imageKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(final ClientData obj) {
|
public int compareTo(final ClientData obj) {
|
||||||
if (obj == null) { return -1; }
|
if (obj == null) { return -1; }
|
||||||
@@ -194,4 +200,25 @@ final public class ClientData implements Comparable<ClientData> {
|
|||||||
public LocalDate getActivationDate() {
|
public LocalDate getActivationDate() {
|
||||||
return this.activationDate;
|
return this.activationDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setImageData(ImageData imageData){
|
||||||
|
this.imageData = imageData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String imageName() {
|
||||||
|
return imageData.name();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String imageContentType() {
|
||||||
|
return imageData.contentType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] image(){
|
||||||
|
try{
|
||||||
|
return imageData.getContent();
|
||||||
|
}catch (IOException ioe){
|
||||||
|
logger.error("Error in fetching client image");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package org.mifosplatform.portfolio.client.data;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.poi.util.IOUtils;
|
||||||
|
import org.mifosplatform.infrastructure.core.service.DocumentStore;
|
||||||
|
import org.mifosplatform.infrastructure.core.service.DocumentStoreType;
|
||||||
|
import org.mifosplatform.infrastructure.core.service.ImageUtils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class ImageData {
|
||||||
|
|
||||||
|
private final Long clientId;
|
||||||
|
private final String key;
|
||||||
|
// private final DocumentStoreType storeType;
|
||||||
|
private final String storeType;
|
||||||
|
private File file;
|
||||||
|
private String contentType;
|
||||||
|
private String name;
|
||||||
|
private InputStream inputStream;
|
||||||
|
|
||||||
|
|
||||||
|
public ImageData(Long clientId, String key, String storeType) {
|
||||||
|
this.clientId = clientId;
|
||||||
|
this.key = key;
|
||||||
|
this.storeType = storeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String imageKey() {
|
||||||
|
return this.key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getContent() throws IOException {
|
||||||
|
if(inputStream == null){
|
||||||
|
FileInputStream fileInputStream = new FileInputStream(file);
|
||||||
|
return IOUtils.toByteArray(fileInputStream);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return IOUtils.toByteArray(inputStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String setImageContentType() {
|
||||||
|
String fileName = file.getName();
|
||||||
|
String contentType = ImageUtils.IMAGE_MIME_TYPE.JPEG.getValue();
|
||||||
|
if (StringUtils.endsWith(fileName, ImageUtils.IMAGE_FILE_EXTENSION.GIF.getValue())) {
|
||||||
|
contentType = ImageUtils.IMAGE_MIME_TYPE.GIF.getValue();
|
||||||
|
} else if (StringUtils.endsWith(fileName, ImageUtils.IMAGE_FILE_EXTENSION.PNG.getValue())) {
|
||||||
|
contentType = ImageUtils.IMAGE_MIME_TYPE.PNG.getValue();
|
||||||
|
}
|
||||||
|
return contentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String contentType(){
|
||||||
|
return this.contentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DocumentStoreType storeType() {
|
||||||
|
return DocumentStore.getDocumentStoreType(storeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String name(){
|
||||||
|
return this.file.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setContent(InputStream objectContent) {
|
||||||
|
this.inputStream = objectContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(File file) {
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-30
@@ -5,26 +5,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.client.domain;
|
package org.mifosplatform.portfolio.client.domain;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.persistence.Column;
|
|
||||||
import javax.persistence.Entity;
|
|
||||||
import javax.persistence.JoinColumn;
|
|
||||||
import javax.persistence.JoinTable;
|
|
||||||
import javax.persistence.ManyToMany;
|
|
||||||
import javax.persistence.ManyToOne;
|
|
||||||
import javax.persistence.Table;
|
|
||||||
import javax.persistence.Temporal;
|
|
||||||
import javax.persistence.TemporalType;
|
|
||||||
import javax.persistence.Transient;
|
|
||||||
import javax.persistence.UniqueConstraint;
|
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.joda.time.format.DateTimeFormatter;
|
import org.joda.time.format.DateTimeFormatter;
|
||||||
@@ -39,6 +19,9 @@ import org.mifosplatform.portfolio.client.api.ClientApiConstants;
|
|||||||
import org.mifosplatform.portfolio.group.domain.Group;
|
import org.mifosplatform.portfolio.group.domain.Group;
|
||||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "m_client", uniqueConstraints = { @UniqueConstraint(columnNames = { "account_no" }, name = "account_no_UNIQUE") })
|
@Table(name = "m_client", uniqueConstraints = { @UniqueConstraint(columnNames = { "account_no" }, name = "account_no_UNIQUE") })
|
||||||
public final class Client extends AbstractPersistable<Long> {
|
public final class Client extends AbstractPersistable<Long> {
|
||||||
@@ -79,9 +62,6 @@ public final class Client extends AbstractPersistable<Long> {
|
|||||||
@Column(name = "external_id", length = 100, nullable = true, unique = true)
|
@Column(name = "external_id", length = 100, nullable = true, unique = true)
|
||||||
private String externalId;
|
private String externalId;
|
||||||
|
|
||||||
@Column(name = "image_key", length = 500, nullable = true)
|
|
||||||
private String imageKey;
|
|
||||||
|
|
||||||
@ManyToMany
|
@ManyToMany
|
||||||
@JoinTable(name = "m_group_client", joinColumns = @JoinColumn(name = "client_id"), inverseJoinColumns = @JoinColumn(name = "group_id"))
|
@JoinTable(name = "m_group_client", joinColumns = @JoinColumn(name = "client_id"), inverseJoinColumns = @JoinColumn(name = "group_id"))
|
||||||
private Set<Group> groups;
|
private Set<Group> groups;
|
||||||
@@ -385,13 +365,12 @@ public final class Client extends AbstractPersistable<Long> {
|
|||||||
return this.office.identifiedBy(officeId);
|
return this.office.identifiedBy(officeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String imageKey() {
|
// public String imageKey() {
|
||||||
return imageKey;
|
// }
|
||||||
}
|
//
|
||||||
|
// public void updateImageKey(final String imageKey) {
|
||||||
public void updateImageKey(final String imageKey) {
|
// this.image.setKey(imageKey);
|
||||||
this.imageKey = imageKey;
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
public Long officeId() {
|
public Long officeId() {
|
||||||
return this.office.getId();
|
return this.office.getId();
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.portfolio.client.domain;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.service.DocumentStoreType;
|
||||||
|
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "m_image")
|
||||||
|
public final class Image extends AbstractPersistable<Long> {
|
||||||
|
|
||||||
|
// @Column(name = "`client_id`")
|
||||||
|
@OneToOne()
|
||||||
|
@JoinColumn(name = "`client_id`")
|
||||||
|
private Client client;
|
||||||
|
|
||||||
|
@Column(name = "`key`", length = 500)
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
@Column(name = "`storage_type`", length = 50)
|
||||||
|
private String storeType;
|
||||||
|
|
||||||
|
public Image(Client client, String image_key, DocumentStoreType storeType) {
|
||||||
|
this.client = client;
|
||||||
|
this.key = image_key;
|
||||||
|
this.storeType = storeType.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Image(Client client) {
|
||||||
|
this.client = client;
|
||||||
|
this.key = null;
|
||||||
|
this.storeType = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String updateKey(String key) {
|
||||||
|
setKey(key);
|
||||||
|
return this.key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateStorageType(String documentStoreType) {
|
||||||
|
this.storeType = documentStoreType;
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.portfolio.client.domain;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||||
|
|
||||||
|
public interface ImageRepository extends JpaRepository<Image, Long>, JpaSpecificationExecutor<Client> {
|
||||||
|
Image findOneByClient(Client client);
|
||||||
|
}
|
||||||
+1
@@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.client.service;
|
package org.mifosplatform.portfolio.client.service;
|
||||||
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.mifosplatform.infrastructure.core.service.Page;
|
import org.mifosplatform.infrastructure.core.service.Page;
|
||||||
|
|||||||
+31
-8
@@ -16,6 +16,7 @@ import org.joda.time.LocalDate;
|
|||||||
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
|
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
|
||||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||||
|
import org.mifosplatform.infrastructure.core.service.DocumentStoreFactory;
|
||||||
import org.mifosplatform.infrastructure.core.service.Page;
|
import org.mifosplatform.infrastructure.core.service.Page;
|
||||||
import org.mifosplatform.infrastructure.core.service.PaginationHelper;
|
import org.mifosplatform.infrastructure.core.service.PaginationHelper;
|
||||||
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
|
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
|
||||||
@@ -25,6 +26,7 @@ import org.mifosplatform.organisation.office.service.OfficeReadPlatformService;
|
|||||||
import org.mifosplatform.portfolio.client.data.ClientAccountSummaryCollectionData;
|
import org.mifosplatform.portfolio.client.data.ClientAccountSummaryCollectionData;
|
||||||
import org.mifosplatform.portfolio.client.data.ClientAccountSummaryData;
|
import org.mifosplatform.portfolio.client.data.ClientAccountSummaryData;
|
||||||
import org.mifosplatform.portfolio.client.data.ClientData;
|
import org.mifosplatform.portfolio.client.data.ClientData;
|
||||||
|
import org.mifosplatform.portfolio.client.data.ImageData;
|
||||||
import org.mifosplatform.portfolio.client.domain.ClientEnumerations;
|
import org.mifosplatform.portfolio.client.domain.ClientEnumerations;
|
||||||
import org.mifosplatform.portfolio.client.exception.ClientNotFoundException;
|
import org.mifosplatform.portfolio.client.exception.ClientNotFoundException;
|
||||||
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
|
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
|
||||||
@@ -38,12 +40,14 @@ import org.springframework.jdbc.core.JdbcTemplate;
|
|||||||
import org.springframework.jdbc.core.RowMapper;
|
import org.springframework.jdbc.core.RowMapper;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@Service(value = "clientReadPlatformService")
|
@Service
|
||||||
public class ClientReadPlatformServiceImpl implements ClientReadPlatformService {
|
public class ClientReadPlatformServiceImpl implements ClientReadPlatformService {
|
||||||
|
|
||||||
|
|
||||||
private final JdbcTemplate jdbcTemplate;
|
private final JdbcTemplate jdbcTemplate;
|
||||||
private final PlatformSecurityContext context;
|
private final PlatformSecurityContext context;
|
||||||
private final OfficeReadPlatformService officeReadPlatformService;
|
private final OfficeReadPlatformService officeReadPlatformService;
|
||||||
|
private final DocumentStoreFactory documentStoreFactory;
|
||||||
|
|
||||||
// data mappers
|
// data mappers
|
||||||
private final PaginationHelper<ClientData> paginationHelper = new PaginationHelper<ClientData>();
|
private final PaginationHelper<ClientData> paginationHelper = new PaginationHelper<ClientData>();
|
||||||
@@ -54,9 +58,10 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public ClientReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource,
|
public ClientReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource,
|
||||||
final OfficeReadPlatformService officeReadPlatformService) {
|
final OfficeReadPlatformService officeReadPlatformService, final DocumentStoreFactory documentStoreFactory) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.officeReadPlatformService = officeReadPlatformService;
|
this.officeReadPlatformService = officeReadPlatformService;
|
||||||
|
this.documentStoreFactory = documentStoreFactory;
|
||||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +164,6 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClientData retrieveOne(final Long clientId) {
|
public ClientData retrieveOne(final Long clientId) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
AppUser currentUser = context.authenticatedUser();
|
AppUser currentUser = context.authenticatedUser();
|
||||||
String hierarchy = currentUser.getOffice().getHierarchy();
|
String hierarchy = currentUser.getOffice().getHierarchy();
|
||||||
@@ -173,7 +177,15 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
|||||||
|
|
||||||
Collection<GroupGeneralData> parentGroups = this.jdbcTemplate.query(clientGroupsSql, this.clientGroupsMapper,
|
Collection<GroupGeneralData> parentGroups = this.jdbcTemplate.query(clientGroupsSql, this.clientGroupsMapper,
|
||||||
new Object[] { clientId });
|
new Object[] { clientId });
|
||||||
|
|
||||||
|
String clientImageSql = "select * from m_image where client_id =" + clientId;
|
||||||
|
|
||||||
|
try {
|
||||||
|
ImageData imageData = this.jdbcTemplate.queryForObject(clientImageSql, new ImageMapper());
|
||||||
|
clientData.setImageData(documentStoreFactory.getInstanceFromStorageType(imageData.storeType()).retrieveImage(imageData));
|
||||||
|
} catch (EmptyResultDataAccessException e) {}
|
||||||
return ClientData.setParentGroups(clientData, parentGroups);
|
return ClientData.setParentGroups(clientData, parentGroups);
|
||||||
|
|
||||||
} catch (EmptyResultDataAccessException e) {
|
} catch (EmptyResultDataAccessException e) {
|
||||||
throw new ClientNotFoundException(clientId);
|
throw new ClientNotFoundException(clientId);
|
||||||
}
|
}
|
||||||
@@ -206,8 +218,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
|||||||
final String hierarchy = currentUser.getOffice().getHierarchy();
|
final String hierarchy = currentUser.getOffice().getHierarchy();
|
||||||
final String hierarchySearchString = hierarchy + "%";
|
final String hierarchySearchString = hierarchy + "%";
|
||||||
|
|
||||||
final String sql = "select " + this.membersOfGroupMapper.schema()
|
final String sql = "select " + this.membersOfGroupMapper.schema() + " where o.hierarchy like ? and pgc.group_id = ?";
|
||||||
+ " where o.hierarchy like ? and pgc.group_id = ?";
|
|
||||||
|
|
||||||
return this.jdbcTemplate.query(sql, this.membersOfGroupMapper, new Object[] { hierarchySearchString, groupId });
|
return this.jdbcTemplate.query(sql, this.membersOfGroupMapper, new Object[] { hierarchySearchString, groupId });
|
||||||
}
|
}
|
||||||
@@ -255,7 +266,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
|||||||
final String officeName = rs.getString("officeName");
|
final String officeName = rs.getString("officeName");
|
||||||
|
|
||||||
return ClientData.instance(accountNo, status, officeId, officeName, id, firstname, middlename, lastname, fullname, displayName,
|
return ClientData.instance(accountNo, status, officeId, officeName, id, firstname, middlename, lastname, fullname, displayName,
|
||||||
externalId, activationDate, imageKey);
|
externalId, activationDate, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,11 +310,11 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
|||||||
final String displayName = rs.getString("displayName");
|
final String displayName = rs.getString("displayName");
|
||||||
final String externalId = rs.getString("externalId");
|
final String externalId = rs.getString("externalId");
|
||||||
final LocalDate activationDate = JdbcSupport.getLocalDate(rs, "activationDate");
|
final LocalDate activationDate = JdbcSupport.getLocalDate(rs, "activationDate");
|
||||||
final String imageKey = rs.getString("imageKey");
|
// final String imageKey = rs.getString("imageKey");
|
||||||
final String officeName = rs.getString("officeName");
|
final String officeName = rs.getString("officeName");
|
||||||
|
|
||||||
return ClientData.instance(accountNo, status, officeId, officeName, id, firstname, middlename, lastname, fullname, displayName,
|
return ClientData.instance(accountNo, status, officeId, officeName, id, firstname, middlename, lastname, fullname, displayName,
|
||||||
externalId, activationDate, imageKey);
|
externalId, activationDate, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -325,6 +336,18 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class ImageMapper implements RowMapper<ImageData> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ImageData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||||
|
final Long clientId = rs.getLong("client_id");
|
||||||
|
final String imageKey = rs.getString("key");
|
||||||
|
final String storeType = rs.getString("storage_type");
|
||||||
|
return new ImageData(clientId, imageKey, storeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private static final class ClientLookupMapper implements RowMapper<ClientData> {
|
private static final class ClientLookupMapper implements RowMapper<ClientData> {
|
||||||
|
|
||||||
private final String schema;
|
private final String schema;
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ public interface ClientWritePlatformService {
|
|||||||
CommandProcessingResult deleteClient(Long clientId);
|
CommandProcessingResult deleteClient(Long clientId);
|
||||||
|
|
||||||
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'CREATE_CLIENTIMAGE')")
|
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'CREATE_CLIENTIMAGE')")
|
||||||
CommandProcessingResult saveOrUpdateClientImage(Long clientId, String imageName, InputStream inputStream);
|
CommandProcessingResult saveOrUpdateClientImage(Long clientId, String imageName, InputStream inputStream, Long fileSize);
|
||||||
|
|
||||||
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'CREATE_CLIENTIMAGE')")
|
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'CREATE_CLIENTIMAGE')")
|
||||||
CommandProcessingResult saveOrUpdateClientImage(Long clientId, Base64EncodedImage encodedImage);
|
CommandProcessingResult saveOrUpdateClientImage(Long clientId, Base64EncodedImage encodedImage);
|
||||||
|
|||||||
+48
-44
@@ -5,13 +5,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.client.service;
|
package org.mifosplatform.portfolio.client.service;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.joda.time.format.DateTimeFormat;
|
import org.joda.time.format.DateTimeFormat;
|
||||||
@@ -21,7 +14,8 @@ import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
|||||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||||
import org.mifosplatform.infrastructure.core.domain.Base64EncodedImage;
|
import org.mifosplatform.infrastructure.core.domain.Base64EncodedImage;
|
||||||
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||||
import org.mifosplatform.infrastructure.core.service.FileUtils;
|
import org.mifosplatform.infrastructure.core.service.DocumentStore;
|
||||||
|
import org.mifosplatform.infrastructure.core.service.DocumentStoreFactory;
|
||||||
import org.mifosplatform.infrastructure.documentmanagement.exception.DocumentManagementException;
|
import org.mifosplatform.infrastructure.documentmanagement.exception.DocumentManagementException;
|
||||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||||
import org.mifosplatform.organisation.office.domain.Office;
|
import org.mifosplatform.organisation.office.domain.Office;
|
||||||
@@ -29,10 +23,7 @@ import org.mifosplatform.organisation.office.domain.OfficeRepository;
|
|||||||
import org.mifosplatform.organisation.office.exception.OfficeNotFoundException;
|
import org.mifosplatform.organisation.office.exception.OfficeNotFoundException;
|
||||||
import org.mifosplatform.portfolio.client.api.ClientApiConstants;
|
import org.mifosplatform.portfolio.client.api.ClientApiConstants;
|
||||||
import org.mifosplatform.portfolio.client.data.ClientDataValidator;
|
import org.mifosplatform.portfolio.client.data.ClientDataValidator;
|
||||||
import org.mifosplatform.portfolio.client.domain.AccountNumberGenerator;
|
import org.mifosplatform.portfolio.client.domain.*;
|
||||||
import org.mifosplatform.portfolio.client.domain.AccountNumberGeneratorFactory;
|
|
||||||
import org.mifosplatform.portfolio.client.domain.Client;
|
|
||||||
import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper;
|
|
||||||
import org.mifosplatform.portfolio.client.exception.ClientMustBePendingToBeDeletedException;
|
import org.mifosplatform.portfolio.client.exception.ClientMustBePendingToBeDeletedException;
|
||||||
import org.mifosplatform.portfolio.client.exception.ClientNotFoundException;
|
import org.mifosplatform.portfolio.client.exception.ClientNotFoundException;
|
||||||
import org.mifosplatform.portfolio.group.domain.Group;
|
import org.mifosplatform.portfolio.group.domain.Group;
|
||||||
@@ -47,6 +38,11 @@ import org.springframework.dao.DataIntegrityViolationException;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWritePlatformService {
|
public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWritePlatformService {
|
||||||
|
|
||||||
@@ -59,12 +55,14 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
|||||||
private final GroupRepository groupRepository;
|
private final GroupRepository groupRepository;
|
||||||
private final ClientDataValidator fromApiJsonDeserializer;
|
private final ClientDataValidator fromApiJsonDeserializer;
|
||||||
private final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory;
|
private final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory;
|
||||||
|
private final DocumentStoreFactory documentStoreFactory;
|
||||||
|
private final ImageRepository imageRepository;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public ClientWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
public ClientWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
||||||
final ClientRepositoryWrapper clientRepository, final OfficeRepository officeRepository, final NoteRepository noteRepository,
|
final ClientRepositoryWrapper clientRepository, final OfficeRepository officeRepository, final NoteRepository noteRepository,
|
||||||
final ClientDataValidator fromApiJsonDeserializer, final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory,
|
final ClientDataValidator fromApiJsonDeserializer, final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory,
|
||||||
final GroupRepository groupRepository) {
|
final GroupRepository groupRepository, DocumentStoreFactory documentStoreFactory, ImageRepository imageRepository) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.clientRepository = clientRepository;
|
this.clientRepository = clientRepository;
|
||||||
this.officeRepository = officeRepository;
|
this.officeRepository = officeRepository;
|
||||||
@@ -72,6 +70,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
|||||||
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
|
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
|
||||||
this.accountIdentifierGeneratorFactory = accountIdentifierGeneratorFactory;
|
this.accountIdentifierGeneratorFactory = accountIdentifierGeneratorFactory;
|
||||||
this.groupRepository = groupRepository;
|
this.groupRepository = groupRepository;
|
||||||
|
this.documentStoreFactory = documentStoreFactory;
|
||||||
|
this.imageRepository = imageRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@@ -223,16 +223,16 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
|||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult saveOrUpdateClientImage(final Long clientId, final String imageName, final InputStream inputStream) {
|
public CommandProcessingResult saveOrUpdateClientImage(final Long clientId, final String imageName, final InputStream inputStream, Long fileSize) {
|
||||||
try {
|
try {
|
||||||
final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId);
|
final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId);
|
||||||
String imageUploadLocation = setupForClientImageUpdate(clientId, client);
|
deletePreviousClientImage(clientId, client);
|
||||||
|
|
||||||
String imageLocation = FileUtils.saveToFileSystem(inputStream, imageUploadLocation, imageName);
|
DocumentStore documentStore = this.documentStoreFactory.getInstanceFromConfiguration();
|
||||||
|
String imageLocation = documentStore.saveImage(inputStream, clientId, imageName, fileSize);
|
||||||
return updateClientImage(clientId, client, imageLocation);
|
return updateClientImage(clientId, client, imageLocation, documentStore.getType().getValue());
|
||||||
} catch (IOException ioe) {
|
} catch (DocumentManagementException dme) {
|
||||||
logger.error(ioe.getMessage(), ioe);
|
logger.error(dme.getMessage(), dme);
|
||||||
throw new DocumentManagementException(imageName);
|
throw new DocumentManagementException(imageName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -243,48 +243,52 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
|||||||
|
|
||||||
final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId);
|
final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId);
|
||||||
|
|
||||||
|
Image image = imageRepository.findOneByClient(client);
|
||||||
|
String imageKey = image.getKey();
|
||||||
// delete image from the file system
|
// delete image from the file system
|
||||||
if (StringUtils.isNotEmpty(client.imageKey())) {
|
if (StringUtils.isNotEmpty((imageKey))) {
|
||||||
FileUtils.deleteClientImage(clientId, client.imageKey());
|
DocumentStore documentStore = this.documentStoreFactory.getInstanceFromConfiguration();
|
||||||
|
documentStore.deleteImage(clientId, imageKey);
|
||||||
|
this.imageRepository.delete(image);
|
||||||
}
|
}
|
||||||
return updateClientImage(clientId, client, null);
|
|
||||||
|
return new CommandProcessingResult(clientId) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult saveOrUpdateClientImage(final Long clientId, final Base64EncodedImage encodedImage) {
|
public CommandProcessingResult saveOrUpdateClientImage(final Long clientId, final Base64EncodedImage encodedImage) {
|
||||||
try {
|
try {
|
||||||
final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId);
|
final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId);
|
||||||
final String imageUploadLocation = setupForClientImageUpdate(clientId, client);
|
deletePreviousClientImage(clientId, client);
|
||||||
|
|
||||||
final String imageLocation = FileUtils.saveToFileSystem(encodedImage, imageUploadLocation, "image");
|
DocumentStore documentStore = this.documentStoreFactory.getInstanceFromConfiguration();
|
||||||
|
final String imageLocation = documentStore.saveImage(encodedImage, clientId, "image");
|
||||||
|
|
||||||
return updateClientImage(clientId, client, imageLocation);
|
return updateClientImage(clientId, client, imageLocation, documentStore.getType().getValue());
|
||||||
} catch (IOException ioe) {
|
} catch (DocumentManagementException dme) {
|
||||||
logger.error(ioe.getMessage(), ioe);
|
logger.error(dme.getMessage(), dme);
|
||||||
throw new DocumentManagementException("image");
|
throw new DocumentManagementException("image");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String setupForClientImageUpdate(final Long clientId, final Client client) {
|
private void deletePreviousClientImage(final Long clientId, final Client client) {
|
||||||
if (client == null) { throw new ClientNotFoundException(clientId); }
|
if (client == null) { throw new ClientNotFoundException(clientId); }
|
||||||
|
|
||||||
final String imageUploadLocation = FileUtils.generateClientImageParentDirectory(clientId);
|
Image image = imageRepository.findOneByClient(client);
|
||||||
// delete previous image from the file system
|
if (image != null){
|
||||||
if (StringUtils.isNotEmpty(client.imageKey())) {
|
this.documentStoreFactory.getInstanceFromConfiguration().deleteImage(clientId, image.getKey());
|
||||||
FileUtils.deleteClientImage(clientId, client.imageKey());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Recursively create the directory if it does not exist **/
|
|
||||||
if (!new File(imageUploadLocation).isDirectory()) {
|
|
||||||
new File(imageUploadLocation).mkdirs();
|
|
||||||
}
|
|
||||||
return imageUploadLocation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CommandProcessingResult updateClientImage(final Long clientId, final Client client, final String imageLocation) {
|
private CommandProcessingResult updateClientImage(final Long clientId, final Client client, final String imageLocation, final String documentStoreType) {
|
||||||
client.updateImageKey(imageLocation);
|
Image image = imageRepository.findOneByClient(client);
|
||||||
this.clientRepository.save(client);
|
if(image == null){
|
||||||
|
image = new Image(client);
|
||||||
|
}
|
||||||
|
image.updateKey(imageLocation);
|
||||||
|
image.updateStorageType(documentStoreType);
|
||||||
|
|
||||||
|
this.imageRepository.save(image);
|
||||||
return new CommandProcessingResult(clientId);
|
return new CommandProcessingResult(clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
package org.mifosplatform.infrastructure.configuration.domain;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mifosplatform.useradministration.domain.Permission;
|
||||||
|
import org.mifosplatform.useradministration.domain.PermissionRepository;
|
||||||
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class ConfigurationDomainServiceJpaTest {
|
||||||
|
|
||||||
|
private final String S3 = "amazon-S3";
|
||||||
|
private PermissionRepository permissionRepositoryMock = mock(PermissionRepository.class);;
|
||||||
|
private GlobalConfigurationRepository globalConfigurationRepositoryMock = mock(GlobalConfigurationRepository.class);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldReturnTrueIfAmazonS3ConfigurationIsEnabled(){
|
||||||
|
when(globalConfigurationRepositoryMock.findOneByName(S3)).thenReturn(new GlobalConfigurationProperty(S3, true));
|
||||||
|
ConfigurationDomainServiceJpa configurationDomainServiceJpa = new ConfigurationDomainServiceJpa(permissionRepositoryMock, globalConfigurationRepositoryMock);
|
||||||
|
|
||||||
|
boolean actualIsS3Enabled = configurationDomainServiceJpa.isAmazonS3Enabled();
|
||||||
|
|
||||||
|
assertTrue(actualIsS3Enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldReturnFalseIfAmazonS3ConfigurationIsDisabled(){
|
||||||
|
when(globalConfigurationRepositoryMock.findOneByName(S3)).thenReturn(new GlobalConfigurationProperty(S3, false));
|
||||||
|
ConfigurationDomainServiceJpa configurationDomainServiceJpa = new ConfigurationDomainServiceJpa(permissionRepositoryMock, globalConfigurationRepositoryMock);
|
||||||
|
|
||||||
|
boolean actualIsS3Enabled = configurationDomainServiceJpa.isAmazonS3Enabled();
|
||||||
|
|
||||||
|
assertFalse(actualIsS3Enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
+55
@@ -0,0 +1,55 @@
|
|||||||
|
package org.mifosplatform.infrastructure.core.service;
|
||||||
|
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mifosplatform.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||||
|
import org.mifosplatform.infrastructure.configuration.domain.ExternalServicesDomainService;
|
||||||
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class DocumentStoreFactoryTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldReturnS3DocumentStoreObjectIfS3Enabled(){
|
||||||
|
S3ClientFactory s3ClientFactoryMock = mock(S3ClientFactory.class);
|
||||||
|
when(s3ClientFactoryMock.getS3Client()).thenReturn(null);
|
||||||
|
|
||||||
|
ExternalServicesDomainService externalServicesDomainServiceMock = mock(ExternalServicesDomainService.class);
|
||||||
|
when(externalServicesDomainServiceMock.getValue("s3_bucket_name")).thenReturn("bucket_name");
|
||||||
|
|
||||||
|
ConfigurationDomainService configurationDomainServiceMock = mock(ConfigurationDomainService.class);
|
||||||
|
when(configurationDomainServiceMock.isAmazonS3Enabled()).thenReturn(true);
|
||||||
|
|
||||||
|
ApplicationContext applicationContextMock = mock(ApplicationContext.class);
|
||||||
|
|
||||||
|
when(applicationContextMock.getBean("configurationDomainServiceJpa", ConfigurationDomainService.class)).thenReturn(configurationDomainServiceMock);
|
||||||
|
when(applicationContextMock.getBean("s3ClientFactory", S3ClientFactory.class)).thenReturn(s3ClientFactoryMock);
|
||||||
|
when(applicationContextMock.getBean("externalServicesDomainService", ExternalServicesDomainService.class)).thenReturn(externalServicesDomainServiceMock);
|
||||||
|
|
||||||
|
|
||||||
|
DocumentStoreFactory documentStoreFactory = new DocumentStoreFactory(applicationContextMock);
|
||||||
|
assertEquals(documentStoreFactory.getInstanceFromConfiguration().getClass(),S3DocumentStore.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldReturnFileSystemDocumentStoreObjectIfS3IsDisabled(){
|
||||||
|
ConfigurationDomainService configurationDomainService = mock(ConfigurationDomainService.class);
|
||||||
|
when(configurationDomainService.isAmazonS3Enabled()).thenReturn(false);
|
||||||
|
|
||||||
|
ApplicationContext applicationContext = mock(ApplicationContext.class);
|
||||||
|
when(applicationContext.getBean("configurationDomainServiceJpa", ConfigurationDomainService.class)).thenReturn(configurationDomainService);
|
||||||
|
|
||||||
|
DocumentStoreFactory documentStoreFactory = new DocumentStoreFactory(applicationContext);
|
||||||
|
assertEquals(documentStoreFactory.getInstanceFromConfiguration().getClass(),FileSystemDocumentStore.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
package org.mifosplatform.infrastructure.core.service;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.data.DocumentData;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.data.FileData;
|
||||||
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class FileDocumentStoreTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldRetrieveDocument(){
|
||||||
|
FileSystemDocumentStore fileSystemDocumentStore = new FileSystemDocumentStore();
|
||||||
|
DocumentData documentDataMock = mock(DocumentData.class);
|
||||||
|
when(documentDataMock.fileName()).thenReturn("some_file");
|
||||||
|
when(documentDataMock.fileName()).thenReturn("content_type");
|
||||||
|
when(documentDataMock.fileLocation()).thenReturn("abcd");
|
||||||
|
|
||||||
|
FileData fileData = fileSystemDocumentStore.retrieveDocument(documentDataMock);
|
||||||
|
|
||||||
|
assertEquals(fileData.name(), documentDataMock.fileName());
|
||||||
|
assertEquals(fileData.contentType(), documentDataMock.contentType());
|
||||||
|
}
|
||||||
|
}
|
||||||
+135
@@ -0,0 +1,135 @@
|
|||||||
|
package org.mifosplatform.infrastructure.core.service;
|
||||||
|
|
||||||
|
import com.amazonaws.AmazonClientException;
|
||||||
|
import com.amazonaws.AmazonServiceException;
|
||||||
|
import com.amazonaws.services.s3.AmazonS3Client;
|
||||||
|
import com.amazonaws.services.s3.model.*;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.command.DocumentCommand;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.data.DocumentData;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.data.FileData;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.exception.DocumentManagementException;
|
||||||
|
import org.mifosplatform.infrastructure.documentmanagement.exception.DocumentNotFoundException;
|
||||||
|
import org.mockito.Matchers;
|
||||||
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class S3DocumentStoreTest {
|
||||||
|
|
||||||
|
InputStream inputStream;
|
||||||
|
AmazonS3Client s3ClientMock;
|
||||||
|
DocumentCommand documentCommand;
|
||||||
|
DocumentData documentDataMock;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldGenerateParentDirectoryFromEntityDetails(){
|
||||||
|
S3DocumentStore s3DocumentStore=new S3DocumentStore("bucketName", null);
|
||||||
|
String actualParentDirectory = s3DocumentStore.generateFileParentDirectory("entity_type", 1234L);
|
||||||
|
assertTrue(actualParentDirectory.startsWith("documents/entity_type/1234"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldGenerateClientImageDirectoryFromResourceId(){
|
||||||
|
S3DocumentStore s3DocumentStore=new S3DocumentStore("bucketName", null);
|
||||||
|
String actualParentDirectory = s3DocumentStore.generateClientImageParentDirectory(1234L);
|
||||||
|
assertTrue(actualParentDirectory.startsWith("images/clients/1234"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldSaveADocumentToS3() throws IOException {
|
||||||
|
initUpload();
|
||||||
|
when(s3ClientMock.putObject(Matchers.<PutObjectRequest>anyObject())).thenReturn(new PutObjectResult());
|
||||||
|
S3DocumentStore s3DocumentStore = new S3DocumentStore("bucketName", s3ClientMock);
|
||||||
|
|
||||||
|
s3DocumentStore.saveDocument(inputStream, documentCommand);
|
||||||
|
|
||||||
|
verify(s3ClientMock, times(1)).putObject(Matchers.<PutObjectRequest>anyObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = DocumentManagementException.class)
|
||||||
|
public void shouldCatchAmazonServiceExceptionWhenUnableToUploadDocumentToS3() throws IOException {
|
||||||
|
initUpload();
|
||||||
|
when(s3ClientMock.putObject(Matchers.<PutObjectRequest>anyObject())).thenThrow(new AmazonServiceException("serviceException"));
|
||||||
|
|
||||||
|
S3DocumentStore s3DocumentStore = new S3DocumentStore("bucketName", s3ClientMock);
|
||||||
|
|
||||||
|
s3DocumentStore.saveDocument(inputStream, documentCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = DocumentManagementException.class)
|
||||||
|
public void shouldCatchAmazonClientExceptionWhenUnableToUploadDocumentToS3() throws IOException {
|
||||||
|
initUpload();
|
||||||
|
when(s3ClientMock.putObject(Matchers.<PutObjectRequest>anyObject())).thenThrow(new AmazonClientException("clientException"));
|
||||||
|
|
||||||
|
S3DocumentStore s3DocumentStore = new S3DocumentStore("bucketName", s3ClientMock);
|
||||||
|
|
||||||
|
s3DocumentStore.saveDocument(inputStream, documentCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldRetrieveDocumentFromS3() throws IOException {
|
||||||
|
initRetrieve();
|
||||||
|
when(s3ClientMock.getObject(Matchers.<GetObjectRequest>anyObject())).thenReturn(new S3Object());
|
||||||
|
S3DocumentStore s3DocumentStore = new S3DocumentStore("bucketName",s3ClientMock);
|
||||||
|
|
||||||
|
FileData fileData = s3DocumentStore.retrieveDocument(documentDataMock);
|
||||||
|
|
||||||
|
verify(s3ClientMock, times(1)).getObject(Matchers.<GetObjectRequest>anyObject());
|
||||||
|
assertEquals(fileData.name(), "name");
|
||||||
|
assertEquals(fileData.contentType(), "type");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = DocumentNotFoundException.class)
|
||||||
|
public void shouldCatchAmazonServiceExceptionWhenUnableToRetrieveDocumentFromS3() throws IOException {
|
||||||
|
initRetrieve();
|
||||||
|
when(s3ClientMock.getObject(Matchers.<GetObjectRequest>anyObject())).thenThrow(new AmazonServiceException("serviceException"));
|
||||||
|
S3DocumentStore s3DocumentStore = new S3DocumentStore("bucketName",s3ClientMock);
|
||||||
|
|
||||||
|
s3DocumentStore.retrieveDocument(documentDataMock);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = DocumentNotFoundException.class)
|
||||||
|
public void shouldCatchAmazonClientExceptionWhenUnableToRetrieveDocumentFromS3() throws IOException {
|
||||||
|
initRetrieve();
|
||||||
|
when(s3ClientMock.getObject(Matchers.<GetObjectRequest>anyObject())).thenThrow(new AmazonClientException("clientException"));
|
||||||
|
S3DocumentStore s3DocumentStore = new S3DocumentStore("bucketName",s3ClientMock);
|
||||||
|
|
||||||
|
s3DocumentStore.retrieveDocument(documentDataMock);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldDeleteImageFromS3() throws IOException {
|
||||||
|
AmazonS3Client s3ClientMock = mock(AmazonS3Client.class);
|
||||||
|
S3DocumentStore s3DocumentStore = new S3DocumentStore("bucketName",s3ClientMock);
|
||||||
|
|
||||||
|
s3DocumentStore.deleteImage(123L,"imagekey");
|
||||||
|
|
||||||
|
verify(s3ClientMock, times(1)).deleteObject(Matchers.<DeleteObjectRequest>anyObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initRetrieve() {
|
||||||
|
s3ClientMock = mock(AmazonS3Client.class);
|
||||||
|
|
||||||
|
documentDataMock = mock(DocumentData.class);
|
||||||
|
when(documentDataMock.fileLocation()).thenReturn("path");
|
||||||
|
when(documentDataMock.fileName()).thenReturn("name");
|
||||||
|
when(documentDataMock.contentType()).thenReturn("type");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void initUpload(){
|
||||||
|
inputStream = S3DocumentStoreTest.class.getResourceAsStream("DummyString");
|
||||||
|
s3ClientMock = mock(AmazonS3Client.class);
|
||||||
|
documentCommand = new DocumentCommand(null, -1l, "parentEntityType", 1l, null, "someFileName", 3l, null, null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user