package org.smoothbuild.builtin.java; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; import org.smoothbuild.builtin.compress.Constants; 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 JarFunction { @SmoothFunction public static Blob jar(Container container, Array<SFile> files, Blob manifest) { DuplicatesDetector<String> duplicatesDetector = new DuplicatesDetector<>(); byte[] buffer = new byte[Constants.BUFFER_SIZE]; BlobBuilder blobBuilder = container.create().blobBuilder(); try (JarOutputStream jarOutputStream = createOutputStream(blobBuilder, manifest)) { for (SFile file : files) { String path = file.path().value(); if (duplicatesDetector.addValue(path)) { throw new ErrorMessage("Cannot jar two files with the same path = " + path); } jarFile(file, jarOutputStream, buffer); } } catch (IOException e) { throw new FileSystemException(e); } return blobBuilder.build(); } private static JarOutputStream createOutputStream(BlobBuilder blobBuilder, Blob manifest) throws IOException { OutputStream outputStream = blobBuilder; if (manifest == null) { return new JarOutputStream(outputStream); } else { try (InputStream manifestStream = manifest.openInputStream()) { return new JarOutputStream(outputStream, new Manifest(manifestStream)); } } } private static void jarFile(SFile file, JarOutputStream jarOutputStream, byte[] buffer) throws IOException { jarOutputStream.putNextEntry(new JarEntry(file.path().value())); try (InputStream inputStream = file.content().openInputStream()) { int readCount = inputStream.read(buffer); while (readCount > 0) { jarOutputStream.write(buffer, 0, readCount); readCount = inputStream.read(buffer); } } jarOutputStream.closeEntry(); } }