code: private void addDirectory(File root, File directory, String targetPath, ZipOutputStream zos) throws IOException {
          String prefix = targetPath;
          if (!prefix.isEmpty() && !prefix.endsWith("/")) {
              prefix += "/";
          }
          // directory entries are required, or else bundle classpath may be
          // broken
          if (!directory.equals(root)) {
              String path = normalizePath(root, directory);
              ZipEntry jarEntry = new ZipEntry(prefix + path + "/");
              jarOutputStream.putNextEntry(jarEntry);
          }
          File[] children = directory.listFiles();
          // loop through dirList, and zip the files
          for (File child : children) {
              if (child.isDirectory()) {
                  addDirectory(root, child, prefix, jarOutputStream);
              }
              else {
                  addFile(root, child, prefix, jarOutputStream);
              }
          }
      }
docs: Recursively adds the contents of the given directory and all subdirectories to the given ZIP
  output stream.
  
  @param root
  an ancestor of {@code directory}, used to determine the relative path within the
  archive
  @param directory
  current directory to be added
  @param zos
  ZIP output stream
  @throws IOException