< prev index next >
test/lib/jdk/test/lib/util/JarUtils.java
Print this page
rev 51882 : [mq]: 8211171-1
*** 21,55 ****
* questions.
*/
package jdk.test.lib.util;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
/**
! * Common library for various test jar file utility functions.
*/
public final class JarUtils {
/**
* Create jar file with specified files. If a specified file does not exist,
* a new jar entry will be created with the file name itself as the content.
*/
public static void createJar(String dest, String... files)
throws IOException {
try (JarOutputStream jos = new JarOutputStream(
new FileOutputStream(dest), new Manifest())) {
for (String file : files) {
--- 21,197 ----
* questions.
*/
package jdk.test.lib.util;
+ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
+ import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
+ import java.nio.file.StandardCopyOption;
+ import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
+ import java.util.List;
import java.util.Map;
+ import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
+ import java.util.stream.Collectors;
+ import java.util.stream.Stream;
/**
! * This class consists exclusively of static utility methods that are useful
! * for creating and manipulating JAR files.
*/
public final class JarUtils {
+ private JarUtils() { }
+
+ /**
+ * Creates a JAR file.
+ *
+ * Equivalent to {@code jar cfm <jarfile> <manifest> -C <dir> file...}
+ *
+ * The input files are resolved against the given directory. Any input
+ * files that are directories are processed recursively.
+ */
+ public static void createJarFile(Path jarfile, Manifest man, Path dir, Path... files)
+ throws IOException
+ {
+ // create the target directory
+ Path parent = jarfile.getParent();
+ if (parent != null) {
+ Files.createDirectories(parent);
+ }
+
+ List<Path> entries = findAllRegularFiles(dir, files);
+
+ try (OutputStream out = Files.newOutputStream(jarfile);
+ JarOutputStream jos = new JarOutputStream(out)) {
+ if (man != null) {
+ JarEntry je = new JarEntry(JarFile.MANIFEST_NAME);
+ jos.putNextEntry(je);
+ man.write(jos);
+ jos.closeEntry();
+ }
+
+ for (Path entry : entries) {
+ String name = toJarEntryName(entry);
+ jos.putNextEntry(new JarEntry(name));
+ Files.copy(dir.resolve(entry), jos);
+ jos.closeEntry();
+ }
+ }
+ }
+
+ /**
+ * Creates a JAR file.
+ *
+ * Equivalent to {@code jar cf <jarfile> -C <dir> file...}
+ *
+ * The input files are resolved against the given directory. Any input
+ * files that are directories are processed recursively.
+ */
+ public static void createJarFile(Path jarfile, Path dir, Path... files)
+ throws IOException
+ {
+ createJarFile(jarfile, null, dir, files);
+ }
+
+ /**
+ * Creates a JAR file from the contents of a directory.
+ *
+ * Equivalent to {@code jar cf <jarfile> -C <dir> .}
+ */
+ public static void createJarFile(Path jarfile, Path dir) throws IOException {
+ createJarFile(jarfile, dir, Paths.get("."));
+ }
+
+
+ /**
+ * Creates a JAR file.
+ *
+ * Equivalent to {@code jar cf <jarfile> -C <dir> file...}
+ *
+ * The input files are resolved against the given directory. Any input
+ * files that are directories are processed recursively.
+ */
+ public static void createJarFile(Path jarfile, Path dir, String... input)
+ throws IOException
+ {
+ Path[] paths = Stream.of(input).map(Paths::get).toArray(Path[]::new);
+ createJarFile(jarfile, dir, paths);
+ }
+
+ /**
+ * Updates a JAR file.
+ *
+ * Equivalent to {@code jar uf <jarfile> -C <dir> file...}
+ *
+ * The input files are resolved against the given directory. Any input
+ * files that are directories are processed recursively.
+ */
+ public static void updateJarFile(Path jarfile, Path dir, Path... files)
+ throws IOException
+ {
+ List<Path> entries = findAllRegularFiles(dir, files);
+
+ Set<String> names = entries.stream()
+ .map(JarUtils::toJarEntryName)
+ .collect(Collectors.toSet());
+
+ Path tmpfile = Files.createTempFile("jar", "jar");
+
+ try (OutputStream out = Files.newOutputStream(tmpfile);
+ JarOutputStream jos = new JarOutputStream(out)) {
+ // copy existing entries from the original JAR file
+ try (JarFile jf = new JarFile(jarfile.toString())) {
+ Enumeration<JarEntry> jentries = jf.entries();
+ while (jentries.hasMoreElements()) {
+ JarEntry jentry = jentries.nextElement();
+ if (!names.contains(jentry.getName())) {
+ jos.putNextEntry(jentry);
+ jf.getInputStream(jentry).transferTo(jos);
+ }
+ }
+ }
+
+ // add the new entries
+ for (Path entry : entries) {
+ String name = toJarEntryName(entry);
+ jos.putNextEntry(new JarEntry(name));
+ Files.copy(dir.resolve(entry), jos);
+ }
+ }
+
+ // replace the original JAR file
+ Files.move(tmpfile, jarfile, StandardCopyOption.REPLACE_EXISTING);
+ }
+
+ /**
+ * Updates a JAR file.
+ *
+ * Equivalent to {@code jar uf <jarfile> -C <dir> .}
+ */
+ public static void updateJarFile(Path jarfile, Path dir) throws IOException {
+ updateJarFile(jarfile, dir, Paths.get("."));
+ }
+
/**
* Create jar file with specified files. If a specified file does not exist,
* a new jar entry will be created with the file name itself as the content.
*/
+ @Deprecated
public static void createJar(String dest, String... files)
throws IOException {
try (JarOutputStream jos = new JarOutputStream(
new FileOutputStream(dest), new Manifest())) {
for (String file : files) {
*** 79,88 ****
--- 221,231 ----
* by a "-" string. The files before in the 1st group will
* be either updated or added. The files in the 2nd group
* will be removed. If no "-" exists, all files belong to
* the 1st group.
*/
+ @Deprecated
public static void updateJar(String src, String dest, String... files)
throws IOException {
Map<String,Object> changes = new HashMap<>();
boolean update = true;
for (String file : files) {
*** 116,125 ****
--- 259,269 ----
* Value can be Path, byte[] or String. If key exists in
* src but value is Boolean FALSE. The entry is removed.
* Existing entries in src not a key is unmodified.
* @throws IOException
*/
+ @Deprecated
public static void updateJar(String src, String dest,
Map<String,Object> changes)
throws IOException {
// What if input changes is immutable?
*** 170,175 ****
--- 314,341 ----
} else {
throw new RuntimeException("Unknown type " + content.getClass());
}
}
}
+
+ /**
+ * Maps a file path to the equivalent name in a JAR file
+ */
+ private static String toJarEntryName(Path file) {
+ Path normalized = file.normalize();
+ return normalized.subpath(0, normalized.getNameCount()) // drop root
+ .toString()
+ .replace(File.separatorChar, '/');
+ }
+
+ private static List<Path> findAllRegularFiles(Path dir, Path[] files) throws IOException {
+ List<Path> entries = new ArrayList<>();
+ for (Path file : files) {
+ try (Stream<Path> stream = Files.find(dir.resolve(file), Integer.MAX_VALUE,
+ (p, attrs) -> attrs.isRegularFile())) {
+ stream.map(dir::relativize)
+ .forEach(entries::add);
+ }
+ }
+ return entries;
+ }
}
< prev index next >