<commit_before>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) {
    return new Worker(container, files, manifest).execute();
  }

  private static class Worker {
    private final Container container;
    private final Array<SFile> files;
    private final Blob manifest;

    private final byte[] buffer = new byte[Constants.BUFFER_SIZE];
    private final DuplicatesDetector<String> duplicatesDetector;

    public Worker(Container container, Array<SFile> files, Blob manifest) {
      this.container = container;
      this.files = files;
      this.manifest = manifest;
      this.duplicatesDetector = new DuplicatesDetector<>();
    }

    public Blob execute() {
      BlobBuilder blobBuilder = container.create().blobBuilder();
      try (JarOutputStream jarOutputStream = createOutputStream(blobBuilder)) {
        for (SFile file : files) {
          addEntry(jarOutputStream, file);
        }
      } catch (IOException e) {
        throw new FileSystemException(e);
      }

      return blobBuilder.build();
    }

    private JarOutputStream createOutputStream(BlobBuilder blobBuilder) throws IOException {
      OutputStream outputStream = blobBuilder;
      if (manifest == null) {
        return new JarOutputStream(outputStream);
      } else {
        try (InputStream manifestStream = manifest.openInputStream()) {
          Manifest manifest = new Manifest(manifestStream);
          return new JarOutputStream(outputStream, manifest);
        }
      }
    }

    private void addEntry(JarOutputStream jarOutputStream, SFile file) throws IOException {
      String path = file.path().value();
      if (duplicatesDetector.addValue(path)) {
        throw new ErrorMessage("Cannot jar two files with the same path = " + path);
      }
      JarEntry entry = new JarEntry(path);
      jarOutputStream.putNextEntry(entry);

      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();
    }
  }
}<commit_msg>refactored JarFunction to not use Worker<commit_after>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();
  }
}
{'fraction_non_alphanumeric': 0.09824561403508772, 'fraction_numerical': 0.0007386888273314866, 'mean_word_length': 3.7550482879719054, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5042447', 'n_tokens_mistral': 1500, 'n_tokens_neox': 1451, 'n_words': 347}