package managers;
import models.Account;
import models.Folder;
import models.Media;
import models.enums.GroupType;
import models.enums.LinkType;
import models.services.ElasticsearchService;
import play.Configuration;
import play.Logger;
import play.db.jpa.JPAApi;
import java.io.IOException;
import java.nio.file.Files;
import javax.inject.Inject;
import java.io.File;
import java.io.FileNotFoundException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* Created by Iven on 17.12.2015.
*/
public class MediaManager implements BaseManager {
final Logger.ALogger LOG = Logger.of(MediaManager.class);
@Inject
NotificationManager notificationManager;
@Inject
Configuration configuration;
@Inject
GroupAccountManager groupAccountManager;
@Inject
ElasticsearchService elasticsearchService;
@Inject
JPAApi jpaApi;
final String tempPrefix = "htwplus_temp";
@Override
public void create(Object model) {
Media media = (Media) model;
media.size = media.file.length();
media.url = createRelativeURL() + "/" + getUniqueFileName(media.fileName);
try {
createFile(media);
jpaApi.em().persist(media);
elasticsearchService.index(media);
} catch (Exception e) {
try {
throw e;
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
@Override
public void update(Object model) {
jpaApi.em().merge(model);
}
@Override
public void delete(Object model) {
Media media = (Media) model;
try {
// remove deprecated notifications
notificationManager.deleteReferences(media);
deleteFile(media);
jpaApi.em().remove(media);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
@SuppressWarnings("unchecked")
public List<Media> findAll() {
return jpaApi.em().createQuery("FROM Media").getResultList();
}
public Media findById(Long id) {
Media media = jpaApi.em().find(Media.class, id);
if (media == null) {
return null;
}
String path = configuration.getString("media.path");
media.file = new File(path + "/" + media.url);
if (media.file.exists()) {
return media;
} else {
return null;
}
}
@SuppressWarnings("unchecked")
public List<Media> findByFolder(Long folderId) {
List<Media> mediaList = jpaApi.em().createQuery("FROM Media m WHERE m.folder.id = " + folderId).getResultList();
List<Media> returningMediaList = new ArrayList<>();
for (Media media : mediaList) {
String path = configuration.getString("media.path");
media.file = new File(path + "/" + media.url);
if (media.file.exists()) {
returningMediaList.add(media);
}
}
return returningMediaList;
}
@SuppressWarnings("unchecked")
public List<Media> listAllOwnedBy(Long id) {
return jpaApi.em().createQuery("FROM Media m WHERE m.owner.id = " + id).getResultList();
}
public boolean existsInFolder(String mediaTitle, Folder folder) {
List<Media> mediaList = findByFolder(folder.id);
for (Media media : mediaList) {
if (media.title.equals(mediaTitle)) {
return true;
}
}
return false;
}
public boolean isOwner(Long mediaId, Account account) {
Media m = jpaApi.em().find(Media.class, mediaId);
if (m.owner.equals(account)) {
return true;
} else {
return false;
}
}
private String getUniqueFileName(String fileName) {
return UUID.randomUUID().toString() + '_' + fileName;
}
private void deleteFile(Media media) throws FileNotFoundException {
String path = configuration.getString("media.path");
File file = new File(path + "/" + media.url);
if (file.exists()) {
file.delete();
} else {
throw new FileNotFoundException("File does not exist.");
}
}
private void createFile(Media media) throws Exception {
String path = configuration.getString("media.path");
File newFile = new File(path + "/" + media.url);
if (newFile.exists()) {
throw new Exception("File exists already");
}
newFile.getParentFile().mkdirs();
Files.move(media.file.toPath(), newFile.toPath());
if (!newFile.exists()) {
throw new Exception("Could not upload file");
}
}
private String createRelativeURL() {
Date now = new Date();
String format = new SimpleDateFormat("yyyy/MM/dd").format(now);
return format;
}
public String bytesToString(long bytes, boolean si) {
int unit = si ? 1000 : 1024;
if (bytes < unit) return bytes + " B";
int exp = (int) (Math.log(bytes) / Math.log(unit));
String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i");
return String.format("%.2f %sB", bytes / Math.pow(unit, exp), pre);
}
/**
* Cleans the temporary media directoy used for ZIP Downloads
*/
public void cleanUpTemp() {
LOG.info("Cleaning the Tempory Media Directory");
String tmpPath = configuration.getString("media.tempPath");
File dir = new File(tmpPath);
LOG.debug("Directory: " + dir.toString());
File[] files = dir.listFiles();
LOG.debug("Absolut Path: " + dir.getAbsolutePath());
if (files != null) {
// Just delete files older than 1 hour
long hours = 1;
long eligibleForDeletion = System.currentTimeMillis() - (hours * 60 * 60 * 1000L);
LOG.info("Found " + files.length + " Files");
if (files != null) {
for (File file : files) {
LOG.info("Working on " + file.getName());
if (file.getName().startsWith(tempPrefix) && file.lastModified() < eligibleForDeletion) {
LOG.info("Deleting: " + file.getName());
file.delete();
}
}
}
} else {
LOG.info("files is null");
}
}
public int byteAsMB(long size) {
return (int) (size / 1024 / 1024);
}
public long indexAllMedia() throws IOException {
final long start = System.currentTimeMillis();
for (Media medium : findAll()) elasticsearchService.index(medium);
return (System.currentTimeMillis() - start) / 1000;
}
/**
* Collect all AccountIds, which are able to view this medium
*
* @return List of AccountIds
*/
public Set<Long> findAllowedToViewAccountIds(Media medium) {
Set<Long> viewableIds = new HashSet<>();
Folder rootFolder = medium.findRoot();
// medium belongs to account
if (rootFolder.account != null) {
viewableIds.add(rootFolder.owner.id);
}
// medium belongs to group
if(rootFolder.group != null) {
viewableIds.addAll(groupAccountManager.findAccountIdsByGroup(rootFolder.group, LinkType.establish));
}
return viewableIds;
}
public boolean isPublic(Media medium) {
if(medium.findGroup() != null) {
return medium.findGroup().groupType.equals(GroupType.open);
}
return false;
}
}