/*
* Copyright (c) Huawei Technologies Co., Ltd. 2022-2024. All rights reserved.
*/
package zip4cj.tasks
public class AddStreamToZipTask <: AbstractAddFileToZipTask<AddStreamToZipTaskParameters> {
public AddStreamToZipTask(
zipModel: ZipModel,
password: ?Array<Rune>,
headerWriter: HeaderWriter,
asyncTaskParameters: AsyncTaskParameters
) {
super(zipModel, password, headerWriter, asyncTaskParameters)
}
protected func executeTask(taskParameters: AddStreamToZipTaskParameters, progressMonitor: ProgressMonitor) {
verifyZipParameters(taskParameters.zipParameters)
if (!Zip4cjUtil.isStringNotNullAndNotEmpty(taskParameters.zipParameters.getFileNameInZip())) {
throw ZipException("fileNameInZip has to be set in zipParameters when adding stream")
}
removeFileIfExists(getZipModel(), taskParameters.zip4cjConfig,
taskParameters.zipParameters.getFileNameInZip().getOrThrow(), progressMonitor)
// For streams, it is necessary to write extended local file header because of Zip standard encryption.
// If we do not write extended local file header, zip standard encryption needs a crc upfront for key,
// which cannot be calculated until we read the complete stream. If we use extended local file header,
// last modified file time is used, or current system time if not available.
taskParameters.zipParameters.setWriteExtendedLocalFileHeader(true)
if (taskParameters.zipParameters.getCompressionMethod() == (CompressionMethod.STORE)) {
// Set some random value here. This will be updated again when closing entry
taskParameters.zipParameters.setEntrySize(0)
}
let splitOutputStream = SplitOutputStream(
getZipModel().getZipFile(),
getZipModel().getSplitLength()
)
let zipOutputStream = initializeOutputStream(splitOutputStream, taskParameters.zip4cjConfig)
try {
var readBuff = Array<Byte>(taskParameters.zip4cjConfig.getBufferSize(), repeat: 0)
var readLen: Int64
var zipParameters = taskParameters.zipParameters
zipOutputStream.putNextEntry(zipParameters)
if (!zipParameters.getFileNameInZip().getOrThrow().endsWith("/") &&
!zipParameters.getFileNameInZip().getOrThrow().endsWith("\\")) {
readLen = taskParameters.inputStream.read(readBuff)
while (readLen > 0) {
zipOutputStream.write(readBuff[0..readLen])
readLen = taskParameters.inputStream.read(readBuff)
}
}
var fileHeader = zipOutputStream.closeEntry()
if (CompressionMethod.STORE == (Zip4cjUtil.getCompressionMethod(fileHeader))) {
updateLocalFileHeader(fileHeader, splitOutputStream)
}
} finally {
zipOutputStream.close()
splitOutputStream.close()
}
}
protected func calculateTotalWork(taskParameters: AddStreamToZipTaskParameters): Int64 {
taskParameters
return 0
}
private func removeFileIfExists(
zipModel: ZipModel,
zip4cjConfig: Zip4cjConfig,
fileNameInZip: String,
progressMonitor: ProgressMonitor
) {
var fileHeader = HeaderUtil.getFileHeader(zipModel, fileNameInZip)
if (fileHeader.isSome()) {
removeFile(fileHeader.getOrThrow(), progressMonitor, zip4cjConfig)
}
}
}