package org.smoothbuild.builtin.compress;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.smoothbuild.io.fs.base.FileSystemException;
import org.smoothbuild.lang.message.ErrorMessage;
import org.smoothbuild.lang.plugin.Container;
import org.smoothbuild.lang.plugin.SmoothFunction;
import org.smoothbuild.lang.value.Array;
import org.smoothbuild.lang.value.Blob;
import org.smoothbuild.lang.value.BlobBuilder;
import org.smoothbuild.lang.value.SFile;
import org.smoothbuild.util.DuplicatesDetector;
public class ZipFunction {
@SmoothFunction
public static Blob zip(Container container, Array<SFile> files) {
byte[] buffer = new byte[Constants.BUFFER_SIZE];
DuplicatesDetector<String> duplicatesDetector = new DuplicatesDetector<>();
BlobBuilder blobBuilder = container.create().blobBuilder();
try (ZipOutputStream zipOutputStream = new ZipOutputStream(blobBuilder)) {
for (SFile file : files) {
String path = file.path().value();
if (duplicatesDetector.addValue(path)) {
throw new ErrorMessage("Cannot zip two files with the same path = " + path);
}
zipFile(file, zipOutputStream, buffer);
}
} catch (IOException e) {
throw new FileSystemException(e);
}
return blobBuilder.build();
}
private static void zipFile(SFile file, ZipOutputStream zipOutputStream, byte[] buffer)
throws IOException {
ZipEntry entry = new ZipEntry(file.path().value());
zipOutputStream.putNextEntry(entry);
try (InputStream inputStream = file.content().openInputStream()) {
int readCount = inputStream.read(buffer);
while (readCount > 0) {
zipOutputStream.write(buffer, 0, readCount);
readCount = inputStream.read(buffer);
}
}
zipOutputStream.closeEntry();
}
}