10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.tools.jar;
27
28 import java.io.*;
29 import java.lang.module.Configuration;
30 import java.lang.module.InvalidModuleDescriptorException;
31 import java.lang.module.ModuleDescriptor;
32 import java.lang.module.ModuleDescriptor.Exports;
33 import java.lang.module.ModuleDescriptor.Provides;
34 import java.lang.module.ModuleDescriptor.Opens;
35 import java.lang.module.ModuleDescriptor.Requires;
36 import java.lang.module.ModuleDescriptor.Version;
37 import java.lang.module.ModuleFinder;
38 import java.lang.module.ModuleReader;
39 import java.lang.module.ModuleReference;
40 import java.lang.module.ResolutionException;
41 import java.lang.module.ResolvedModule;
42 import java.net.URI;
43 import java.nio.ByteBuffer;
44 import java.nio.file.Path;
45 import java.nio.file.Files;
46 import java.nio.file.Paths;
47 import java.nio.file.StandardCopyOption;
48 import java.util.*;
49 import java.util.function.Consumer;
390 extract(fname, files);
391 } else {
392 InputStream in = (fname == null)
393 ? new FileInputStream(FileDescriptor.in)
394 : new FileInputStream(fname);
395 try {
396 if (!extract(new BufferedInputStream(in), files) && fname != null) {
397 extract(fname, files);
398 }
399 } finally {
400 in.close();
401 }
402 }
403 } else if (iflag) {
404 String[] files = filesMap.get(BASE_VERSION); // base entries only, can be null
405 genIndex(rootjar, files);
406 } else if (dflag) {
407 boolean found;
408 if (fname != null) {
409 try (ZipFile zf = new ZipFile(fname)) {
410 found = printModuleDescriptor(zf);
411 }
412 } else {
413 try (FileInputStream fin = new FileInputStream(FileDescriptor.in)) {
414 found = printModuleDescriptor(fin);
415 }
416 }
417 if (!found)
418 error(getMsg("error.module.descriptor.not.found"));
419 }
420 } catch (IOException e) {
421 fatalError(e);
422 ok = false;
423 } catch (Error ee) {
424 ee.printStackTrace();
425 ok = false;
426 } catch (Throwable t) {
427 t.printStackTrace();
428 ok = false;
429 } finally {
430 if (tmpFile != null && tmpFile.exists())
431 tmpFile.delete();
432 }
433 out.flush();
434 err.flush();
586 default:
587 usageError(formatMsg("error.illegal.option",
588 String.valueOf(flags.charAt(i))));
589 return false;
590 }
591 }
592 }
593 } catch (ArrayIndexOutOfBoundsException e) {
594 usageError(getMsg("main.usage.summary"));
595 return false;
596 }
597 if (!cflag && !tflag && !xflag && !uflag && !iflag && !dflag) {
598 usageError(getMsg("error.bad.option"));
599 return false;
600 }
601
602 /* parse file arguments */
603 int n = args.length - count;
604 if (n > 0) {
605 if (dflag) {
606 // "--print-module-descriptor/-d" does not require file argument(s)
607 usageError(formatMsg("error.bad.dflag", args[count]));
608 return false;
609 }
610 int version = BASE_VERSION;
611 int k = 0;
612 String[] nameBuf = new String[n];
613 pathsMap.put(version, new HashSet<>());
614 try {
615 for (int i = count; i < args.length; i++) {
616 if (args[i].equals("-C")) {
617 /* change the directory */
618 String dir = args[++i];
619 dir = (dir.endsWith(File.separator) ?
620 dir : (dir + File.separator));
621 dir = dir.replace(File.separatorChar, '/');
622 while (dir.indexOf("//") > -1) {
623 dir = dir.replace("//", "/");
624 }
625 pathsMap.get(version).add(dir.replace(File.separatorChar, '/'));
626 nameBuf[k++] = dir + args[++i];
1711 }
1712 } else {
1713 // No options left - we can not compress to stdout without access to the temporary folder
1714 fatalError(new IOException(getMsg("error.create.tempfile")));
1715 }
1716 }
1717 return tmpfile;
1718 }
1719
1720 // Modular jar support
1721
1722 static <T> String toString(Collection<T> c,
1723 CharSequence prefix,
1724 CharSequence suffix ) {
1725 if (c.isEmpty())
1726 return "";
1727 return c.stream().map(e -> e.toString())
1728 .collect(joining(", ", prefix, suffix));
1729 }
1730
1731 private boolean printModuleDescriptor(ZipFile zipFile)
1732 throws IOException
1733 {
1734 ZipEntry[] zes = zipFile.stream()
1735 .filter(e -> isModuleInfoEntry(e.getName()))
1736 .sorted(Validator.ENTRY_COMPARATOR)
1737 .toArray(ZipEntry[]::new);
1738 if (zes.length == 0)
1739 return false;
1740 for (ZipEntry ze : zes) {
1741 try (InputStream is = zipFile.getInputStream(ze)) {
1742 printModuleDescriptor(is, ze.getName());
1743 }
1744 }
1745 return true;
1746 }
1747
1748 private boolean printModuleDescriptor(FileInputStream fis)
1749 throws IOException
1750 {
1751 try (BufferedInputStream bis = new BufferedInputStream(fis);
1752 ZipInputStream zis = new ZipInputStream(bis)) {
1753 ZipEntry e;
1754 while ((e = zis.getNextEntry()) != null) {
1755 String ename = e.getName();
1756 if (isModuleInfoEntry(ename)){
1757 moduleInfos.put(ename, zis.readAllBytes());
1758 }
1759 }
1760 }
1761 if (moduleInfos.size() == 0)
1762 return false;
1763 String[] names = moduleInfos.keySet().stream()
1764 .sorted(Validator.ENTRYNAME_COMPARATOR)
1765 .toArray(String[]::new);
1766 for (String name : names) {
1767 printModuleDescriptor(new ByteArrayInputStream(moduleInfos.get(name)), name);
1768 }
1769 return true;
1770 }
1771
1772 static <T> String toString(Collection<T> set) {
1773 if (set.isEmpty()) { return ""; }
1774 return set.stream().map(e -> e.toString().toLowerCase(Locale.ROOT))
1775 .collect(joining(" "));
1776 }
1777
1778 private void printModuleDescriptor(InputStream entryInputStream, String ename)
1779 throws IOException
1780 {
1781 ModuleInfo.Attributes attrs = ModuleInfo.read(entryInputStream, null);
1782 ModuleDescriptor md = attrs.descriptor();
1783 ModuleHashes hashes = attrs.recordedHashes();
1784
1785 StringBuilder sb = new StringBuilder();
1786 sb.append("\nmodule ")
1787 .append(md.toNameAndVersion())
1788 .append(" (").append(ename).append(")");
1789
1790 if (md.isOpen())
1791 sb.append("\n open ");
1792
1793 md.requires().stream()
1794 .sorted(Comparator.comparing(Requires::name))
1795 .forEach(r -> {
1796 sb.append("\n requires ");
1797 if (!r.modifiers().isEmpty())
1798 sb.append(toString(r.modifiers())).append(" ");
1799 sb.append(r.name());
1800 });
1801
1802 md.uses().stream().sorted()
1803 .forEach(p -> sb.append("\n uses ").append(p));
1804
|
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.tools.jar;
27
28 import java.io.*;
29 import java.lang.module.Configuration;
30 import java.lang.module.FindException;
31 import java.lang.module.InvalidModuleDescriptorException;
32 import java.lang.module.ModuleDescriptor;
33 import java.lang.module.ModuleDescriptor.Exports;
34 import java.lang.module.ModuleDescriptor.Provides;
35 import java.lang.module.ModuleDescriptor.Opens;
36 import java.lang.module.ModuleDescriptor.Requires;
37 import java.lang.module.ModuleDescriptor.Version;
38 import java.lang.module.ModuleFinder;
39 import java.lang.module.ModuleReader;
40 import java.lang.module.ModuleReference;
41 import java.lang.module.ResolutionException;
42 import java.lang.module.ResolvedModule;
43 import java.net.URI;
44 import java.nio.ByteBuffer;
45 import java.nio.file.Path;
46 import java.nio.file.Files;
47 import java.nio.file.Paths;
48 import java.nio.file.StandardCopyOption;
49 import java.util.*;
50 import java.util.function.Consumer;
391 extract(fname, files);
392 } else {
393 InputStream in = (fname == null)
394 ? new FileInputStream(FileDescriptor.in)
395 : new FileInputStream(fname);
396 try {
397 if (!extract(new BufferedInputStream(in), files) && fname != null) {
398 extract(fname, files);
399 }
400 } finally {
401 in.close();
402 }
403 }
404 } else if (iflag) {
405 String[] files = filesMap.get(BASE_VERSION); // base entries only, can be null
406 genIndex(rootjar, files);
407 } else if (dflag) {
408 boolean found;
409 if (fname != null) {
410 try (ZipFile zf = new ZipFile(fname)) {
411 found = describeModule(zf);
412 }
413 } else {
414 try (FileInputStream fin = new FileInputStream(FileDescriptor.in)) {
415 found = describeModule(fin);
416 }
417 }
418 if (!found)
419 error(getMsg("error.module.descriptor.not.found"));
420 }
421 } catch (IOException e) {
422 fatalError(e);
423 ok = false;
424 } catch (Error ee) {
425 ee.printStackTrace();
426 ok = false;
427 } catch (Throwable t) {
428 t.printStackTrace();
429 ok = false;
430 } finally {
431 if (tmpFile != null && tmpFile.exists())
432 tmpFile.delete();
433 }
434 out.flush();
435 err.flush();
587 default:
588 usageError(formatMsg("error.illegal.option",
589 String.valueOf(flags.charAt(i))));
590 return false;
591 }
592 }
593 }
594 } catch (ArrayIndexOutOfBoundsException e) {
595 usageError(getMsg("main.usage.summary"));
596 return false;
597 }
598 if (!cflag && !tflag && !xflag && !uflag && !iflag && !dflag) {
599 usageError(getMsg("error.bad.option"));
600 return false;
601 }
602
603 /* parse file arguments */
604 int n = args.length - count;
605 if (n > 0) {
606 if (dflag) {
607 // "--describe-module/-d" does not require file argument(s)
608 usageError(formatMsg("error.bad.dflag", args[count]));
609 return false;
610 }
611 int version = BASE_VERSION;
612 int k = 0;
613 String[] nameBuf = new String[n];
614 pathsMap.put(version, new HashSet<>());
615 try {
616 for (int i = count; i < args.length; i++) {
617 if (args[i].equals("-C")) {
618 /* change the directory */
619 String dir = args[++i];
620 dir = (dir.endsWith(File.separator) ?
621 dir : (dir + File.separator));
622 dir = dir.replace(File.separatorChar, '/');
623 while (dir.indexOf("//") > -1) {
624 dir = dir.replace("//", "/");
625 }
626 pathsMap.get(version).add(dir.replace(File.separatorChar, '/'));
627 nameBuf[k++] = dir + args[++i];
1712 }
1713 } else {
1714 // No options left - we can not compress to stdout without access to the temporary folder
1715 fatalError(new IOException(getMsg("error.create.tempfile")));
1716 }
1717 }
1718 return tmpfile;
1719 }
1720
1721 // Modular jar support
1722
1723 static <T> String toString(Collection<T> c,
1724 CharSequence prefix,
1725 CharSequence suffix ) {
1726 if (c.isEmpty())
1727 return "";
1728 return c.stream().map(e -> e.toString())
1729 .collect(joining(", ", prefix, suffix));
1730 }
1731
1732 private boolean describeModule(ZipFile zipFile) throws IOException {
1733 ZipEntry[] zes = zipFile.stream()
1734 .filter(e -> isModuleInfoEntry(e.getName()))
1735 .sorted(Validator.ENTRY_COMPARATOR)
1736 .toArray(ZipEntry[]::new);
1737
1738 if (zes.length == 0) {
1739 // No module descriptor found, derive the automatic module name
1740 String fn = zipFile.getName();
1741 ModuleFinder mf = ModuleFinder.of(Paths.get(fn));
1742 try {
1743 Set<ModuleReference> mref = mf.findAll();
1744 if (mref.isEmpty()) {
1745 output(formatMsg("error.unable.derive.automodule", fn));
1746 return true;
1747 }
1748 ModuleDescriptor md = mref.iterator().next().descriptor();
1749 output(getMsg("out.automodule"));
1750 describeModule(md, null, "automatic");
1751 } catch (FindException e) {
1752 String msg = formatMsg("error.unable.derive.automodule", fn);
1753 Throwable t = e.getCause();
1754 if (t != null)
1755 msg = msg + "\n" + t.getMessage();
1756 output(msg);
1757 }
1758 } else {
1759 for (ZipEntry ze : zes) {
1760 try (InputStream is = zipFile.getInputStream(ze)) {
1761 describeModule(is, ze.getName());
1762 }
1763 }
1764 }
1765 return true;
1766 }
1767
1768 private boolean describeModule(FileInputStream fis)
1769 throws IOException
1770 {
1771 try (BufferedInputStream bis = new BufferedInputStream(fis);
1772 ZipInputStream zis = new ZipInputStream(bis)) {
1773 ZipEntry e;
1774 while ((e = zis.getNextEntry()) != null) {
1775 String ename = e.getName();
1776 if (isModuleInfoEntry(ename)){
1777 moduleInfos.put(ename, zis.readAllBytes());
1778 }
1779 }
1780 }
1781 if (moduleInfos.size() == 0)
1782 return false;
1783 String[] names = moduleInfos.keySet().stream()
1784 .sorted(Validator.ENTRYNAME_COMPARATOR)
1785 .toArray(String[]::new);
1786 for (String name : names) {
1787 describeModule(new ByteArrayInputStream(moduleInfos.get(name)), name);
1788 }
1789 return true;
1790 }
1791
1792 static <T> String toString(Collection<T> set) {
1793 if (set.isEmpty()) { return ""; }
1794 return set.stream().map(e -> e.toString().toLowerCase(Locale.ROOT))
1795 .collect(joining(" "));
1796 }
1797
1798 private void describeModule(InputStream entryInputStream, String ename)
1799 throws IOException
1800 {
1801 ModuleInfo.Attributes attrs = ModuleInfo.read(entryInputStream, null);
1802 ModuleDescriptor md = attrs.descriptor();
1803 ModuleHashes hashes = attrs.recordedHashes();
1804
1805 describeModule(md, hashes, ename);
1806 }
1807
1808 private void describeModule(ModuleDescriptor md,
1809 ModuleHashes hashes,
1810 String ename)
1811 throws IOException
1812 {
1813 StringBuilder sb = new StringBuilder();
1814 sb.append("\nmodule ")
1815 .append(md.toNameAndVersion())
1816 .append(" (").append(ename).append(")");
1817
1818 if (md.isOpen())
1819 sb.append("\n open ");
1820
1821 md.requires().stream()
1822 .sorted(Comparator.comparing(Requires::name))
1823 .forEach(r -> {
1824 sb.append("\n requires ");
1825 if (!r.modifiers().isEmpty())
1826 sb.append(toString(r.modifiers())).append(" ");
1827 sb.append(r.name());
1828 });
1829
1830 md.uses().stream().sorted()
1831 .forEach(p -> sb.append("\n uses ").append(p));
1832
|