/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.sync.engine.document.library.util;
import com.liferay.sync.engine.document.library.event.AddFileEntryEvent;
import com.liferay.sync.engine.document.library.event.AddFolderEvent;
import com.liferay.sync.engine.document.library.event.CancelCheckOutEvent;
import com.liferay.sync.engine.document.library.event.CheckInFileEntryEvent;
import com.liferay.sync.engine.document.library.event.CheckOutFileEntryEvent;
import com.liferay.sync.engine.document.library.event.CopyFileEntryEvent;
import com.liferay.sync.engine.document.library.event.DownloadFileEvent;
import com.liferay.sync.engine.document.library.event.Event;
import com.liferay.sync.engine.document.library.event.GetAllFolderSyncDLObjectsEvent;
import com.liferay.sync.engine.document.library.event.GetSyncDLObjectUpdateEvent;
import com.liferay.sync.engine.document.library.event.LanDownloadFileEvent;
import com.liferay.sync.engine.document.library.event.MoveFileEntryEvent;
import com.liferay.sync.engine.document.library.event.MoveFileEntryToTrashEvent;
import com.liferay.sync.engine.document.library.event.MoveFolderEvent;
import com.liferay.sync.engine.document.library.event.MoveFolderToTrashEvent;
import com.liferay.sync.engine.document.library.event.PatchFileEntryEvent;
import com.liferay.sync.engine.document.library.event.UpdateFileEntryEvent;
import com.liferay.sync.engine.document.library.event.UpdateFolderEvent;
import com.liferay.sync.engine.document.library.handler.GetAllFolderSyncDLObjectsHandler;
import com.liferay.sync.engine.model.SyncAccount;
import com.liferay.sync.engine.model.SyncFile;
import com.liferay.sync.engine.model.SyncSite;
import com.liferay.sync.engine.service.SyncAccountService;
import com.liferay.sync.engine.service.SyncFileService;
import com.liferay.sync.engine.service.SyncPropService;
import com.liferay.sync.engine.service.SyncSiteService;
import com.liferay.sync.engine.util.FileUtil;
import com.liferay.sync.engine.util.IODeltaUtil;
import com.liferay.sync.engine.util.PropsValues;
import com.liferay.sync.engine.util.ReleaseInfo;
import com.liferay.sync.engine.util.ServerInfo;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Shinn Lok
*/
public class FileEventUtil {
public static void addFile(
Path filePath, long folderId, long repositoryId, long syncAccountId,
String checksum, String name, String mimeType, SyncFile syncFile) {
Map<String, Object> parameters = new HashMap<>();
parameters.put("changeLog", getChangeLog());
parameters.put("checksum", checksum);
parameters.put("description", "");
parameters.put("filePath", filePath);
parameters.put("folderId", folderId);
parameters.put("mimeType", mimeType);
parameters.put("repositoryId", repositoryId);
parameters.put("serviceContext.attributes.overwrite", true);
parameters.put("sourceFileName", name);
parameters.put("syncFile", syncFile);
parameters.put("title", name);
AddFileEntryEvent addFileEntryEvent = new AddFileEntryEvent(
syncAccountId, parameters);
addFileEntryEvent.run();
}
public static void addFolder(
long parentFolderId, long repositoryId, long syncAccountId, String name,
SyncFile syncFile) {
Map<String, Object> parameters = new HashMap<>();
parameters.put("description", "");
parameters.put("name", name);
parameters.put("parentFolderId", parentFolderId);
parameters.put("repositoryId", repositoryId);
parameters.put("serviceContext.attributes.overwrite", true);
parameters.put("syncFile", syncFile);
AddFolderEvent addFolderEvent = new AddFolderEvent(
syncAccountId, parameters);
addFolderEvent.run();
}
public static void cancelCheckOut(long syncAccountId, SyncFile syncFile) {
Map<String, Object> parameters = new HashMap<>();
parameters.put("fileEntryId", syncFile.getTypePK());
parameters.put("syncFile", syncFile);
CancelCheckOutEvent cancelCheckOutEvent = new CancelCheckOutEvent(
syncAccountId, parameters);
cancelCheckOutEvent.run();
}
public static void checkInFile(long syncAccountId, SyncFile syncFile) {
Map<String, Object> parameters = new HashMap<>();
parameters.put("changeLog", syncFile.getChangeLog());
parameters.put("fileEntryId", syncFile.getTypePK());
parameters.put("majorVersion", false);
parameters.put("syncFile", syncFile);
CheckInFileEntryEvent checkInFileEntryEvent = new CheckInFileEntryEvent(
syncAccountId, parameters);
checkInFileEntryEvent.run();
}
public static void checkOutFile(long syncAccountId, SyncFile syncFile) {
Map<String, Object> parameters = new HashMap<>();
parameters.put("fileEntryId", syncFile.getTypePK());
parameters.put("syncFile", syncFile);
CheckOutFileEntryEvent checkOutFileEntryEvent =
new CheckOutFileEntryEvent(syncAccountId, parameters);
checkOutFileEntryEvent.run();
}
public static void copyFile(
long sourceFileEntryId, long folderId, long repositoryId,
long syncAccountId, String name, SyncFile syncFile) {
Map<String, Object> parameters = new HashMap<>();
parameters.put("folderId", folderId);
parameters.put("repositoryId", repositoryId);
parameters.put("sourceFileEntryId", sourceFileEntryId);
parameters.put("sourceFileName", name);
parameters.put("syncFile", syncFile);
parameters.put("title", name);
CopyFileEntryEvent copyFileEntryEvent = new CopyFileEntryEvent(
syncAccountId, parameters);
copyFileEntryEvent.run();
}
public static void deleteFile(long syncAccountId, SyncFile syncFile) {
SyncFile parentSyncFile = SyncFileService.fetchSyncFile(
syncFile.getRepositoryId(), syncAccountId,
syncFile.getParentFolderId());
if ((parentSyncFile == null) ||
(parentSyncFile.getUiEvent() == SyncFile.UI_EVENT_DELETED_LOCAL)) {
return;
}
Map<String, Object> parameters = new HashMap<>();
parameters.put("fileEntryId", syncFile.getTypePK());
parameters.put("syncFile", syncFile);
MoveFileEntryToTrashEvent moveFileEntryToTrashEvent =
new MoveFileEntryToTrashEvent(syncAccountId, parameters);
moveFileEntryToTrashEvent.run();
}
public static void deleteFolder(long syncAccountId, SyncFile syncFile) {
SyncFile parentSyncFile = SyncFileService.fetchSyncFile(
syncFile.getRepositoryId(), syncAccountId,
syncFile.getParentFolderId());
if ((parentSyncFile == null) ||
(parentSyncFile.getUiEvent() == SyncFile.UI_EVENT_DELETED_LOCAL)) {
return;
}
Map<String, Object> parameters = new HashMap<>();
parameters.put("folderId", syncFile.getTypePK());
parameters.put("syncFile", syncFile);
MoveFolderToTrashEvent moveFolderToTrashEvent =
new MoveFolderToTrashEvent(syncAccountId, parameters);
moveFolderToTrashEvent.run();
}
public static void downloadFile(long syncAccountId, SyncFile syncFile) {
downloadFile(syncAccountId, syncFile, true);
}
public static void downloadFile(
long syncAccountId, SyncFile syncFile, boolean batch) {
downloadFile(syncAccountId, syncFile, batch, true);
}
public static void downloadFile(
long syncAccountId, SyncFile syncFile, boolean batch, boolean lan) {
if (isDownloadInProgress(syncFile)) {
return;
}
Map<String, Object> parameters = new HashMap<>();
parameters.put("batch", batch);
parameters.put("patch", false);
parameters.put("syncFile", syncFile);
SyncAccount syncAccount = SyncAccountService.fetchSyncAccount(
syncAccountId);
if (lan && syncAccount.isLanEnabled() &&
SyncPropService.getBoolean("lanEnabled", true) &&
StringUtils.isNotEmpty(syncFile.getLanTokenKey()) &&
(syncFile.getSize() >= (syncAccount.getBatchFileMaxSize() / 10))) {
Event event = new LanDownloadFileEvent(syncAccountId, parameters);
event.run();
}
else {
Event event = new DownloadFileEvent(syncAccountId, parameters);
event.run();
}
}
public static void downloadPatch(
long sourceVersionId, long syncAccountId, SyncFile syncFile,
long targetVersionId) {
if (isDownloadInProgress(syncFile)) {
return;
}
Map<String, Object> parameters = new HashMap<>();
parameters.put("batch", true);
parameters.put("patch", true);
parameters.put("sourceVersionId", sourceVersionId);
parameters.put("syncFile", syncFile);
parameters.put("targetVersionId", targetVersionId);
DownloadFileEvent downloadFileEvent = new DownloadFileEvent(
syncAccountId, parameters);
downloadFileEvent.run();
}
public static List<SyncFile> getAllFolders(
long repositoryId, long syncAccountId) {
Map<String, Object> parameters = new HashMap<>();
parameters.put("repositoryId", repositoryId);
SyncSite syncSite = SyncSiteService.fetchSyncSite(
repositoryId, syncAccountId);
SyncFile syncFile = SyncFileService.fetchSyncFile(
syncSite.getFilePathName());
parameters.put("syncFile", syncFile);
GetAllFolderSyncDLObjectsEvent getAllFolderSyncDLObjectsEvent =
new GetAllFolderSyncDLObjectsEvent(syncAccountId, parameters);
getAllFolderSyncDLObjectsEvent.run();
GetAllFolderSyncDLObjectsHandler getAllFolderSyncDLObjectsHandler =
(GetAllFolderSyncDLObjectsHandler)getAllFolderSyncDLObjectsEvent.
getHandler();
return getAllFolderSyncDLObjectsHandler.getSyncFiles();
}
public static void getUpdates(
long repositoryId, long syncAccountId, SyncSite syncSite,
boolean retrieveFromCache) {
Map<String, Object> parameters = new HashMap<>();
parameters.put("repositoryId", repositoryId);
if (ServerInfo.supportsRetrieveFromCache(syncAccountId)) {
parameters.put("retrieveFromCache", retrieveFromCache);
}
SyncFile syncFile = SyncFileService.fetchSyncFile(
syncSite.getFilePathName());
parameters.put("syncFile", syncFile);
parameters.put("syncSite", syncSite);
GetSyncDLObjectUpdateEvent getSyncDLObjectUpdateEvent =
new GetSyncDLObjectUpdateEvent(syncAccountId, parameters);
getSyncDLObjectUpdateEvent.run();
}
public static void moveFile(
long folderId, long syncAccountId, SyncFile syncFile) {
Map<String, Object> parameters = new HashMap<>();
parameters.put("fileEntryId", syncFile.getTypePK());
parameters.put("newFolderId", folderId);
parameters.put(
"serviceContext.scopeGroupId", syncFile.getRepositoryId());
parameters.put("syncFile", syncFile);
MoveFileEntryEvent moveFileEntryEvent = new MoveFileEntryEvent(
syncAccountId, parameters);
moveFileEntryEvent.run();
}
public static void moveFolder(
long parentFolderId, long syncAccountId, SyncFile syncFile) {
Map<String, Object> parameters = new HashMap<>();
parameters.put("folderId", syncFile.getTypePK());
parameters.put("parentFolderId", parentFolderId);
parameters.put(
"serviceContext.scopeGroupId", syncFile.getRepositoryId());
parameters.put("syncFile", syncFile);
MoveFolderEvent moveFolderEvent = new MoveFolderEvent(
syncAccountId, parameters);
moveFolderEvent.run();
}
public static void resyncFolder(long syncAccountId, SyncFile syncFile) {
Map<String, Object> parameters = new HashMap<>();
parameters.put("lastAccessTime", -1);
parameters.put("parentFolderId", syncFile.getTypePK());
parameters.put("repositoryId", syncFile.getRepositoryId());
parameters.put("syncFile", syncFile);
GetSyncDLObjectUpdateEvent getSyncDLObjectUpdateEvent =
new GetSyncDLObjectUpdateEvent(syncAccountId, parameters);
getSyncDLObjectUpdateEvent.run();
}
public static void retryFileTransfers(long syncAccountId)
throws IOException {
List<SyncFile> deletingSyncFiles = SyncFileService.findSyncFiles(
syncAccountId, SyncFile.UI_EVENT_DELETED_LOCAL, "syncFileId", true);
for (SyncFile deletingSyncFile : deletingSyncFiles) {
if (!FileUtil.notExists(
Paths.get(deletingSyncFile.getFilePathName()))) {
deletingSyncFile.setState(SyncFile.STATE_SYNCED);
deletingSyncFile.setUiEvent(SyncFile.UI_EVENT_NONE);
SyncFileService.update(deletingSyncFile);
continue;
}
if (deletingSyncFile.isFolder()) {
deleteFolder(syncAccountId, deletingSyncFile);
}
else {
deleteFile(syncAccountId, deletingSyncFile);
}
}
List<SyncFile> downloadingSyncFiles = SyncFileService.findSyncFiles(
syncAccountId, SyncFile.UI_EVENT_DOWNLOADING, "size", true);
for (SyncFile downloadingSyncFile : downloadingSyncFiles) {
downloadFile(syncAccountId, downloadingSyncFile);
}
BatchEventManager.fireBatchDownloadEvents();
List<SyncFile> uploadingSyncFiles = SyncFileService.findSyncFiles(
syncAccountId, SyncFile.UI_EVENT_UPLOADING, "size", true);
for (SyncFile uploadingSyncFile : uploadingSyncFiles) {
Path filePath = Paths.get(uploadingSyncFile.getFilePathName());
if (FileUtil.notExists(filePath)) {
if (uploadingSyncFile.getTypePK() == 0) {
SyncFileService.deleteSyncFile(uploadingSyncFile, false);
}
continue;
}
if (uploadingSyncFile.isFolder()) {
if (uploadingSyncFile.getTypePK() > 0) {
updateFolder(
filePath, uploadingSyncFile.getSyncAccountId(),
uploadingSyncFile);
}
else {
addFolder(
uploadingSyncFile.getParentFolderId(),
uploadingSyncFile.getRepositoryId(), syncAccountId,
uploadingSyncFile.getName(), uploadingSyncFile);
}
continue;
}
String checksum = FileUtil.getChecksum(filePath);
uploadingSyncFile.setChecksum(checksum);
uploadingSyncFile.setSize(Files.size(filePath));
SyncFileService.update(uploadingSyncFile);
IODeltaUtil.checksums(uploadingSyncFile);
if (uploadingSyncFile.getTypePK() > 0) {
updateFile(
filePath, syncAccountId, uploadingSyncFile, null,
uploadingSyncFile.getName(), "", null, 0, checksum);
}
else {
addFile(
filePath, uploadingSyncFile.getParentFolderId(),
uploadingSyncFile.getRepositoryId(), syncAccountId,
checksum, uploadingSyncFile.getName(),
uploadingSyncFile.getMimeType(), uploadingSyncFile);
}
}
List<SyncFile> movingSyncFiles = SyncFileService.findSyncFiles(
syncAccountId, SyncFile.UI_EVENT_MOVED_LOCAL, "syncFileId", true);
for (SyncFile movingSyncFile : movingSyncFiles) {
if (movingSyncFile.isFolder()) {
moveFolder(
movingSyncFile.getParentFolderId(), syncAccountId,
movingSyncFile);
}
else {
moveFile(
movingSyncFile.getParentFolderId(), syncAccountId,
movingSyncFile);
}
}
BatchEventManager.fireBatchEvents();
List<SyncFile> resyncingSyncFiles = SyncFileService.findSyncFiles(
syncAccountId, SyncFile.UI_EVENT_RESYNCING, "syncFileId", true);
for (SyncFile resyncingSyncFile : resyncingSyncFiles) {
resyncFolder(syncAccountId, resyncingSyncFile);
}
}
public static void updateFile(
Path filePath, long syncAccountId, SyncFile syncFile,
Path deltaFilePath, String name, String sourceChecksum,
String sourceFileName, long sourceVersionId, String targetChecksum)
throws IOException {
Map<String, Object> parameters = new HashMap<>();
parameters.put("changeLog", getChangeLog());
parameters.put("checksum", targetChecksum);
parameters.put("description", syncFile.getDescription());
parameters.put("fileEntryId", syncFile.getTypePK());
parameters.put("majorVersion", false);
parameters.put("mimeType", syncFile.getMimeType());
parameters.put("sourceFileName", name);
parameters.put("syncFile", syncFile);
parameters.put("title", name);
if (FileUtil.checksumsEqual(sourceChecksum, targetChecksum)) {
parameters.put("-file", null);
}
else {
if ((deltaFilePath != null) && (sourceVersionId != 0) &&
((Files.size(filePath) / Files.size(deltaFilePath)) >=
PropsValues.SYNC_FILE_PATCHING_THRESHOLD_SIZE_RATIO)) {
parameters.put("deltaFilePath", deltaFilePath);
parameters.put("sourceFileName", sourceFileName);
parameters.put("sourceVersionId", sourceVersionId);
PatchFileEntryEvent patchFileEntryEvent =
new PatchFileEntryEvent(syncAccountId, parameters);
patchFileEntryEvent.run();
return;
}
parameters.put("filePath", filePath);
}
UpdateFileEntryEvent updateFileEntryEvent = new UpdateFileEntryEvent(
syncAccountId, parameters);
updateFileEntryEvent.run();
}
public static void updateFolder(
Path filePath, long syncAccountId, SyncFile syncFile) {
Map<String, Object> parameters = new HashMap<>();
parameters.put("description", syncFile.getDescription());
parameters.put("folderId", syncFile.getTypePK());
parameters.put("name", String.valueOf(filePath.getFileName()));
parameters.put("syncFile", syncFile);
UpdateFolderEvent updateFolderEvent = new UpdateFolderEvent(
syncAccountId, parameters);
updateFolderEvent.run();
}
protected static String getChangeLog() {
return "Uploaded with Liferay Sync " + ReleaseInfo.getVersion();
}
protected static boolean isDownloadInProgress(SyncFile syncFile) {
Set<Event> events = FileEventManager.getEvents(
syncFile.getSyncFileId());
for (Event event : events) {
if (event instanceof DownloadFileEvent) {
SyncFile downloadingSyncFile =
(SyncFile)event.getParameterValue("syncFile");
if (downloadingSyncFile.getVersionId() !=
syncFile.getVersionId()) {
continue;
}
if (_logger.isDebugEnabled()) {
_logger.debug(
"Download already in progress {}",
syncFile.getFilePathName());
}
return true;
}
}
return false;
}
private static final Logger _logger = LoggerFactory.getLogger(
FileEventUtil.class);
}