package models.services;
import models.base.FileOperationException;
import org.springframework.util.Assert;
import play.Logger;
import play.api.PlayException;
import play.mvc.Http;
import play.api.libs.MimeTypes;
import java.io.IOException;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.Arrays;
/**
* This class acts as a abstraction level for file system operations.
* It encapsulates all basic functions, like creating, reading, copying
* moving and deleting files.
*
* @Todo Not completed yet
*/
public class FileService {
public static String MIME_JPEG = "image/jpeg";
public static String MIME_PNG = "image/png";
private String path;
private String realm;
private File file;
private String contentType;
private String fileName;
/**
* Get a FileService from a basic File
*
* @param realm Namespace of the file
* @param file The File
*/
public FileService(String realm, File file, String path){
this.initPath(realm, path);
this.initProperties(file);
}
/**
* Get a FileService from a Play FilePart
*
* @param realm Namespace of the file
* @param filePart The FilePart
*/
public FileService(String realm, Http.MultipartFormData.FilePart<File> filePart, String path){
this(realm, filePart.getFile(), path);
this.contentType = filePart.getContentType();
this.fileName = filePart.getFilename();
}
/**
* Get a FileService from a file name
*
* @param realm Namespace of the file
* @param fileName The file name
*/
public FileService(String realm, String fileName, String path) throws FileOperationException {
this.initPath(realm, path);
File file = this.openFile(fileName);
if(file == null) {
throw new FileOperationException("File does not exit");
}
this.initProperties(file);
}
/**
* Initiates the path of the files by the realm
*
* @param realm The namespace
*/
private void initPath(String realm, String path) {
this.path = path;
if(this.path == null) {
throw new PlayException(
"Configuration Error",
"The configuration key 'media.fileStore' is not set");
}
this.realm = realm;
Assert.notNull(this.realm, "The realm cannot be null");
}
/**
* Sets the basic properties
*
* @param file The file
*/
private void initProperties(File file) {
this.file = file;
Assert.notNull(this.file, "The file cannot be null");
}
/**
* Opens a file by file name
*
* @param fileName The file name
* @return File
*/
private File openFile(String fileName){
String path = this.buildPath(fileName);
File file = new File(path);
if(file.exists()){
return file;
} else {
return null;
}
}
/**
* Return the actual file
*
* @return File
*/
public File getFile(){
return this.file;
}
/**
* Validates the size of the file
*
* @param size Max Site in Byte
* @return boolean True if valid
*/
public boolean validateSize(long size) {
Assert.notNull(this.file, "The file property is null.");
long fileSize = file.length();
if(fileSize > size){
return false;
} else {
return true;
}
}
/**
* Validates the content type of the file if set
* If not set try to set it with guessContentType()
*
* @param contentTypes Array if allowed content types
* @return boolean True if valid
*/
public boolean validateContentType(String[] contentTypes){
Assert.notNull(this.contentType, "Content type is not set");
MimeTypes.defaultTypes();
if(Arrays.asList(contentTypes).contains(this.contentType)) {
return true;
} else {
return false;
}
}
/**
* Save the file to a custom file name within the realm.
*
* @param fileName The name of the file
* @param overwrite Set to true if already existing file should be overwritten
*/
public void saveFile(String fileName, boolean overwrite) {
Assert.notNull(this.file, "The file property is null.");
String path = this.buildPath(fileName);
Logger.info(path);
File newFile = new File(path);
if(overwrite) {
if(newFile.exists()) {
newFile.delete();
}
}
newFile.getParentFile().mkdirs();
try {
java.nio.file.Files.move(this.file.toPath(), newFile.toPath());
}
catch (IOException e) {
throw new PlayException(
"File Error",
"The file could not be stored");
}
}
/**
* Copy the file and get a new FileService for the new file
*
* @param destFileName The destination file name
* @return FileService
*/
public FileService copy(String destFileName){
String destPath = this.buildPath(destFileName);
File destFile = new File(destPath);
try {
Files.copy(file.toPath(), destFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
return null;
}
if(destFile.exists()){
return new FileService(this.realm, destFile, path);
} else {
return null;
}
}
/**
* Build the actual path for the current file
*
* @param fileName The name of the file
* @return String
*/
private String buildPath(String fileName) {
return this.path + "/" + this.realm + "/" + fileName;
}
public static long MBAsByte(long size) {
return (size * 1024 * 1024);
}
public static long KBAsByte(long size) {
return (size * 1024);
}
}