56 import java.nio.file.Paths;
57 import java.nio.file.SimpleFileVisitor;
58 import java.nio.file.StandardCopyOption;
59 import java.nio.file.attribute.BasicFileAttributes;
60 import java.text.MessageFormat;
61 import java.util.ArrayList;
62 import java.util.Collection;
63 import java.util.Collections;
64 import java.util.Comparator;
65 import java.util.HashSet;
66 import java.util.LinkedHashMap;
67 import java.util.List;
68 import java.util.Locale;
69 import java.util.Map;
70 import java.util.MissingResourceException;
71 import java.util.Optional;
72 import java.util.ResourceBundle;
73 import java.util.Set;
74 import java.util.TreeSet;
75 import java.util.function.Consumer;
76 import java.util.function.Function;
77 import java.util.function.Predicate;
78 import java.util.function.Supplier;
79 import java.util.jar.JarEntry;
80 import java.util.jar.JarFile;
81 import java.util.jar.JarOutputStream;
82 import java.util.stream.Collectors;
83 import java.util.regex.Pattern;
84 import java.util.regex.PatternSyntaxException;
85 import java.util.zip.ZipEntry;
86 import java.util.zip.ZipException;
87 import java.util.zip.ZipFile;
88
89 import jdk.internal.jmod.JmodFile;
90 import jdk.internal.jmod.JmodFile.Section;
91 import jdk.internal.joptsimple.BuiltinHelpFormatter;
92 import jdk.internal.joptsimple.NonOptionArgumentSpec;
93 import jdk.internal.joptsimple.OptionDescriptor;
94 import jdk.internal.joptsimple.OptionException;
95 import jdk.internal.joptsimple.OptionParser;
96 import jdk.internal.joptsimple.OptionSet;
378 .append(toHex(hashes.hashFor(mod))));
379 }
380
381 out.println(sb.toString());
382 }
383
384 private String toHex(byte[] ba) {
385 StringBuilder sb = new StringBuilder(ba.length);
386 for (byte b: ba) {
387 sb.append(String.format("%02x", b & 0xff));
388 }
389 return sb.toString();
390 }
391
392 private boolean create() throws IOException {
393 JmodFileWriter jmod = new JmodFileWriter();
394
395 // create jmod with temporary name to avoid it being examined
396 // when scanning the module path
397 Path target = options.jmodFile;
398 Path tempTarget = Files.createTempFile(target.getFileName().toString(), ".tmp");
399 try {
400 try (JmodOutputStream jos = JmodOutputStream.newOutputStream(tempTarget)) {
401 jmod.write(jos);
402 }
403 Files.move(tempTarget, target);
404 } catch (Exception e) {
405 if (Files.exists(tempTarget)) {
406 try {
407 Files.delete(tempTarget);
408 } catch (IOException ioe) {
409 e.addSuppressed(ioe);
410 }
411 }
412 throw e;
413 }
414 return true;
415 }
416
417 private class JmodFileWriter {
418 final List<Path> cmds = options.cmds;
419 final List<Path> libs = options.libs;
420 final List<Path> configs = options.configs;
421 final List<Path> classpath = options.classpath;
422 final List<Path> headerFiles = options.headerFiles;
423 final List<Path> manPages = options.manPages;
424 final List<Path> legalNotices = options.legalNotices;
425
426 final Version moduleVersion = options.moduleVersion;
427 final String mainClass = options.mainClass;
428 final String osName = options.osName;
429 final String osArch = options.osArch;
430 final String osVersion = options.osVersion;
431 final List<PathMatcher> excludes = options.excludes;
432 final ModuleResolution moduleResolution = options.moduleResolution;
433
434 JmodFileWriter() { }
891 /**
892 * Reads the given input stream of module-info.class and write
893 * the extended module-info.class with the given ModuleHashes
894 *
895 * @param in InputStream of module-info.class
896 * @param out OutputStream to write the extended module-info.class
897 * @param hashes ModuleHashes
898 */
899 private void recordHashes(InputStream in, OutputStream out, ModuleHashes hashes)
900 throws IOException
901 {
902 ModuleInfoExtender extender = ModuleInfoExtender.newExtender(in);
903 extender.hashes(hashes);
904 extender.write(out);
905 }
906
907 void updateModuleInfo(String name, ModuleHashes moduleHashes)
908 throws IOException
909 {
910 Path target = moduleToPath(name);
911 Path tempTarget = Files.createTempFile(target.getFileName().toString(), ".tmp");
912 try {
913 if (target.getFileName().toString().endsWith(".jmod")) {
914 updateJmodFile(target, tempTarget, moduleHashes);
915 } else {
916 updateModularJar(target, tempTarget, moduleHashes);
917 }
918 } catch (IOException|RuntimeException e) {
919 if (Files.exists(tempTarget)) {
920 try {
921 Files.delete(tempTarget);
922 } catch (IOException ioe) {
923 e.addSuppressed(ioe);
924 }
925 }
926 throw e;
927 }
928
929 out.println(getMessage("module.hashes.recorded", name));
930 Files.move(tempTarget, target, StandardCopyOption.REPLACE_EXISTING);
931 }
932
933 private void updateModularJar(Path target, Path tempTarget,
934 ModuleHashes moduleHashes)
935 throws IOException
936 {
937 try (JarFile jf = new JarFile(target.toFile());
938 OutputStream out = Files.newOutputStream(tempTarget);
939 JarOutputStream jos = new JarOutputStream(out))
940 {
941 jf.stream().forEach(e -> {
942 try (InputStream in = jf.getInputStream(e)) {
943 if (e.getName().equals(MODULE_INFO)) {
944 // what about module-info.class in versioned entries?
945 ZipEntry ze = new ZipEntry(e.getName());
946 ze.setTime(System.currentTimeMillis());
947 jos.putNextEntry(ze);
948 recordHashes(in, jos, moduleHashes);
949 jos.closeEntry();
950 } else {
|
56 import java.nio.file.Paths;
57 import java.nio.file.SimpleFileVisitor;
58 import java.nio.file.StandardCopyOption;
59 import java.nio.file.attribute.BasicFileAttributes;
60 import java.text.MessageFormat;
61 import java.util.ArrayList;
62 import java.util.Collection;
63 import java.util.Collections;
64 import java.util.Comparator;
65 import java.util.HashSet;
66 import java.util.LinkedHashMap;
67 import java.util.List;
68 import java.util.Locale;
69 import java.util.Map;
70 import java.util.MissingResourceException;
71 import java.util.Optional;
72 import java.util.ResourceBundle;
73 import java.util.Set;
74 import java.util.TreeSet;
75 import java.util.function.Consumer;
76 import java.util.function.Predicate;
77 import java.util.function.Supplier;
78 import java.util.jar.JarEntry;
79 import java.util.jar.JarFile;
80 import java.util.jar.JarOutputStream;
81 import java.util.stream.Collectors;
82 import java.util.regex.Pattern;
83 import java.util.regex.PatternSyntaxException;
84 import java.util.zip.ZipEntry;
85 import java.util.zip.ZipException;
86 import java.util.zip.ZipFile;
87
88 import jdk.internal.jmod.JmodFile;
89 import jdk.internal.jmod.JmodFile.Section;
90 import jdk.internal.joptsimple.BuiltinHelpFormatter;
91 import jdk.internal.joptsimple.NonOptionArgumentSpec;
92 import jdk.internal.joptsimple.OptionDescriptor;
93 import jdk.internal.joptsimple.OptionException;
94 import jdk.internal.joptsimple.OptionParser;
95 import jdk.internal.joptsimple.OptionSet;
377 .append(toHex(hashes.hashFor(mod))));
378 }
379
380 out.println(sb.toString());
381 }
382
383 private String toHex(byte[] ba) {
384 StringBuilder sb = new StringBuilder(ba.length);
385 for (byte b: ba) {
386 sb.append(String.format("%02x", b & 0xff));
387 }
388 return sb.toString();
389 }
390
391 private boolean create() throws IOException {
392 JmodFileWriter jmod = new JmodFileWriter();
393
394 // create jmod with temporary name to avoid it being examined
395 // when scanning the module path
396 Path target = options.jmodFile;
397 Path tempTarget = jmodTempFilePath(target);
398 try {
399 try (JmodOutputStream jos = JmodOutputStream.newOutputStream(tempTarget)) {
400 jmod.write(jos);
401 }
402 Files.move(tempTarget, target);
403 Files.deleteIfExists(tempTarget.getParent());
404 } catch (Exception e) {
405 deleteTempFile(tempTarget, e);
406 throw e;
407 }
408 return true;
409 }
410
411 /*
412 * Create a JMOD .tmp file for the given target JMOD file in
413 * a temporary directory
414 */
415 private static Path jmodTempFilePath(Path target) throws IOException {
416 String fn = target.getFileName().toString();
417 Path dir = Files.createTempDirectory(fn);
418 return dir.resolve(fn + ".tmp");
419 }
420
421 /**
422 * delete temporary directory and temporary jmod file
423 */
424 private static void deleteTempFile(Path tempTarget, Exception e) {
425 try {
426 Files.deleteIfExists(tempTarget);
427 } catch (IOException ioe) {
428 e.addSuppressed(ioe);
429 }
430
431 Path tmpdir = tempTarget.getParent();
432 try {
433 Files.deleteIfExists(tmpdir);
434 } catch (IOException ioe) {
435 e.addSuppressed(ioe);
436 }
437 }
438
439 private class JmodFileWriter {
440 final List<Path> cmds = options.cmds;
441 final List<Path> libs = options.libs;
442 final List<Path> configs = options.configs;
443 final List<Path> classpath = options.classpath;
444 final List<Path> headerFiles = options.headerFiles;
445 final List<Path> manPages = options.manPages;
446 final List<Path> legalNotices = options.legalNotices;
447
448 final Version moduleVersion = options.moduleVersion;
449 final String mainClass = options.mainClass;
450 final String osName = options.osName;
451 final String osArch = options.osArch;
452 final String osVersion = options.osVersion;
453 final List<PathMatcher> excludes = options.excludes;
454 final ModuleResolution moduleResolution = options.moduleResolution;
455
456 JmodFileWriter() { }
913 /**
914 * Reads the given input stream of module-info.class and write
915 * the extended module-info.class with the given ModuleHashes
916 *
917 * @param in InputStream of module-info.class
918 * @param out OutputStream to write the extended module-info.class
919 * @param hashes ModuleHashes
920 */
921 private void recordHashes(InputStream in, OutputStream out, ModuleHashes hashes)
922 throws IOException
923 {
924 ModuleInfoExtender extender = ModuleInfoExtender.newExtender(in);
925 extender.hashes(hashes);
926 extender.write(out);
927 }
928
929 void updateModuleInfo(String name, ModuleHashes moduleHashes)
930 throws IOException
931 {
932 Path target = moduleToPath(name);
933 Path tempTarget = jmodTempFilePath(target);
934 try {
935 if (target.getFileName().toString().endsWith(".jmod")) {
936 updateJmodFile(target, tempTarget, moduleHashes);
937 } else {
938 updateModularJar(target, tempTarget, moduleHashes);
939 }
940 } catch (IOException|RuntimeException e) {
941 deleteTempFile(tempTarget, e);
942 throw e;
943 }
944
945 out.println(getMessage("module.hashes.recorded", name));
946 Files.move(tempTarget, target, StandardCopyOption.REPLACE_EXISTING);
947 Files.deleteIfExists(tempTarget.getParent());
948 }
949
950 private void updateModularJar(Path target, Path tempTarget,
951 ModuleHashes moduleHashes)
952 throws IOException
953 {
954 try (JarFile jf = new JarFile(target.toFile());
955 OutputStream out = Files.newOutputStream(tempTarget);
956 JarOutputStream jos = new JarOutputStream(out))
957 {
958 jf.stream().forEach(e -> {
959 try (InputStream in = jf.getInputStream(e)) {
960 if (e.getName().equals(MODULE_INFO)) {
961 // what about module-info.class in versioned entries?
962 ZipEntry ze = new ZipEntry(e.getName());
963 ze.setTime(System.currentTimeMillis());
964 jos.putNextEntry(ze);
965 recordHashes(in, jos, moduleHashes);
966 jos.closeEntry();
967 } else {
|