/**
* 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.Event;
import com.liferay.sync.engine.document.library.event.UpdateFileEntriesEvent;
import com.liferay.sync.engine.document.library.handler.Handler;
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.SyncSiteService;
import com.liferay.sync.engine.util.FileUtil;
import com.liferay.sync.engine.util.JSONUtil;
import com.liferay.sync.engine.util.StreamUtil;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Shinn Lok
*/
public class BatchEvent {
public BatchEvent(long syncAccountId, long syncSiteId) throws Exception {
_syncAccountId = syncAccountId;
_syncSiteId = syncSiteId;
}
public synchronized boolean addEvent(Event event) {
SyncAccount syncAccount = SyncAccountService.fetchSyncAccount(
_syncAccountId);
if (syncAccount.getBatchFileMaxSize() <= 0) {
return false;
}
try {
Map<String, Object> parameters = event.getParameters();
SyncFile syncFile = (SyncFile)parameters.get("syncFile");
String zipFileId =
syncFile.getSyncFileId() + "_" + System.currentTimeMillis();
Path deltaFilePath = (Path)parameters.get("deltaFilePath");
Path filePath = (Path)parameters.get("filePath");
if (deltaFilePath != null) {
if (!addFile(
deltaFilePath, zipFileId,
syncAccount.getBatchFileMaxSize())) {
return false;
}
}
else if (filePath != null) {
if (!addFile(
filePath, zipFileId,
syncAccount.getBatchFileMaxSize())) {
return false;
}
}
parameters.put("urlPath", event.getURLPath());
parameters.put("zipFileId", zipFileId);
parameters = new HashMap<>(parameters);
parameters.remove("deltaFilePath");
parameters.remove("filePath");
parameters.remove("syncFile");
_batchParameters.add(parameters);
_eventCount++;
_handlers.put(zipFileId, event.getHandler());
if ((_eventCount >= 250) ||
(_totalFileSize >= syncAccount.getBatchFileMaxSize())) {
fireBatchEvent();
}
return true;
}
catch (IOException ioe) {
if (_logger.isDebugEnabled()) {
_logger.debug(ioe.getMessage(), ioe);
}
return false;
}
}
public synchronized void fireBatchEvent() {
try {
if (_closed || (_eventCount == 0)) {
return;
}
Path filePath = Files.createTempFile("manifest", ".json");
JSONUtil.writeValue(filePath.toFile(), _batchParameters);
writeFilePathToZip(filePath, "manifest.json");
_zipOutputStream.close();
Map<String, Object> parameters = new HashMap<>();
parameters.put("handlers", _handlers);
SyncSite syncSite = SyncSiteService.fetchSyncSite(_syncSiteId);
SyncFile syncFile = SyncFileService.fetchSyncFile(
syncSite.getFilePathName());
parameters.put("syncFile", syncFile);
parameters.put("zipFilePath", _zipFilePath);
UpdateFileEntriesEvent updateFileEntriesEvent =
new UpdateFileEntriesEvent(_syncAccountId, parameters);
updateFileEntriesEvent.run();
_closed = true;
}
catch (Exception e) {
if (_logger.isDebugEnabled()) {
_logger.debug(e.getMessage(), e);
}
}
}
public synchronized boolean isClosed() {
return _closed;
}
protected boolean addFile(
Path filePath, String zipFileId, int batchFileMaxSize)
throws IOException {
long fileSize = Files.size(filePath);
if (fileSize >= (batchFileMaxSize / 10)) {
return false;
}
writeFilePathToZip(filePath, zipFileId);
_totalFileSize += fileSize;
return true;
}
protected void writeFilePathToZip(Path filePath, String name)
throws IOException {
InputStream inputStream = null;
try {
if (_zipOutputStream == null) {
SyncAccount syncAccount = SyncAccountService.fetchSyncAccount(
_syncAccountId);
_zipFilePath = FileUtil.getFilePath(
syncAccount.getFilePathName(), ".data",
String.valueOf(System.currentTimeMillis()) + ".zip");
OutputStream outputStream = Files.newOutputStream(_zipFilePath);
_zipOutputStream = new ZipOutputStream(outputStream);
_zipOutputStream.setLevel(0);
}
ZipEntry zipEntry = new ZipEntry(name);
_zipOutputStream.putNextEntry(zipEntry);
inputStream = Files.newInputStream(filePath);
byte[] buffer = new byte[1024];
int length = 0;
while ((length = inputStream.read(buffer)) > 0) {
_zipOutputStream.write(buffer, 0, length);
}
}
finally {
if (_zipOutputStream != null) {
_zipOutputStream.closeEntry();
}
StreamUtil.cleanUp(inputStream);
}
}
private static final Logger _logger = LoggerFactory.getLogger(
BatchEvent.class);
private final List<Map<String, Object>> _batchParameters =
new ArrayList<>();
private boolean _closed;
private int _eventCount;
private final Map<String, Handler<Void>> _handlers = new HashMap<>();
private final long _syncAccountId;
private final long _syncSiteId;
private long _totalFileSize;
private Path _zipFilePath;
private ZipOutputStream _zipOutputStream;
}