< 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 >