Repository: GoogleContainerTools/jib
File: jib-cli/src/main/java/com/google/cloud/tools/jib/cli/jar/JarModeProcessor.java (Java)

Code before:
      return ImmutableList.of("java", "-cp", classpath, mainClass);
    }
  }

  /**
   * Computes the entrypoint for a standard jar in packaged mode.
   *
   * @param jarPath path to jar file
   * @return list of {@link String} representing entrypoint
   * @throws IOException if I/O error occurs when opening the jar file
   */
  static ImmutableList<String> computeEntrypointForPackagedStandard(Path jarPath)
      throws IOException {
    try (JarFile jarFile = new JarFile(jarPath.toFile())) {
      String mainClass =
          jarFile.getManifest().getMainAttributes().getValue(Attributes.Name.MAIN_CLASS);
      if (mainClass == null) {
        throw new IllegalArgumentException(
            "`Main-Class:` attribute for an application main class not defined in the input JAR's "
                + "manifest (`META-INF/MANIFEST.MF` in the JAR).");
      }
      return ImmutableList.of("java", "-jar", APP_ROOT + "/" + jarPath.getFileName().toString());
    }
  }

  private static ImmutableMap<String, List<Path>> getSnapshotAndNonSnapshotDependencies(
      String classpath) {
    Predicate<String> isSnapshot = name -> name.contains("SNAPSHOT");
    List<String> allDependencies = Splitter.onPattern("\\s+").splitToList(classpath.trim());
    List<Path> nonSnapshotDependencies =
        allDependencies
            .stream()
            .filter(isSnapshot.negate())
            .map(Paths::get)
            .collect(Collectors.toList());
    List<Path> snapshotDependencies =
        allDependencies.stream().filter(isSnapshot).map(Paths::get).collect(Collectors.toList());
    return ImmutableMap.of(
        SNAPSHOT_DEPENDENCIES, snapshotDependencies, DEPENDENCIES, nonSnapshotDependencies);
  }

  private static void addDependency(
      FileEntriesLayer.Builder layerbuilder, Path fullDepPath, AbsoluteUnixPath pathOnContainer) {
    if (!Files.exists(fullDepPath)) {
      throw new IllegalArgumentException(
          String.format(
              "Dependency required by the JAR (as specified in `Class-Path` in the JAR manifest) doesn't exist: %s",
              fullDepPath));
    }
    layerbuilder.addEntry(fullDepPath, pathOnContainer);
  }

Review comment (refactor):
I'm not a big fan of using a map for the purpose of returning more than one value. How about creating a private inner class? For this purpose, I think we don't even need getters and setters.

```java
private static class LocalDependencies {
  private final List<Path> snapshots;
  private final List<Path> nonSnapshots;

  private LocalDependencies(List<Path> snapshots, List<Path> nonSnapshots) {
    this.snapshots = snapshots;
    this.nonSnapshots = nonSnapshots;
  }
}
```

But is it not possible for this method to return built layers? (I remember the original code worked in that way, and I liked it.) In that way, I think we can remove duplicate code between the exploded mode and the packaged mode?

Code after:
        }
        return layers;
      }
    }
  }

  private static void addDependency(
      FileEntriesLayer.Builder layerbuilder, Path fullDepPath, AbsoluteUnixPath pathOnContainer) {
    if (!Files.exists(fullDepPath)) {
      throw new IllegalArgumentException(
          String.format(
              "Dependency required by the JAR (as specified in `Class-Path` in the JAR manifest) doesn't exist: %s",
              fullDepPath));
    }
    layerbuilder.addEntry(fullDepPath, pathOnContainer);
  }

  private static FileEntriesLayer addDirectoryContentsToLayer(
      String layerName,
      Path sourceRoot,
      Predicate<Path> pathFilter,
      AbsoluteUnixPath basePathInContainer)
      throws IOException {
    FileEntriesLayer.Builder builder = FileEntriesLayer.builder().setName(layerName);
    new DirectoryWalker(sourceRoot)
        .filterRoot()
        .filter(path -> Files.isDirectory(path) || pathFilter.test(path))
        .walk(
            path -> {
              AbsoluteUnixPath pathOnContainer =
                  basePathInContainer.resolve(sourceRoot.relativize(path));
              builder.addEntry(path, pathOnContainer);
            });
    return builder.build();
  }
}