1 /*
2 * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 build.tools.jigsaw;
27
28 import java.io.IOException;
29 import java.io.PrintStream;
30 import java.lang.module.Configuration;
31 import java.lang.module.ModuleDescriptor;
32 import java.lang.module.ModuleFinder;
33 import java.lang.module.ModuleReference;
34 import java.lang.module.ResolvedModule;
35 import java.nio.file.Files;
36 import java.nio.file.Path;
37 import java.nio.file.Paths;
38 import java.util.Arrays;
39 import java.util.Comparator;
40 import java.util.Date;
41 import java.util.Enumeration;
42 import java.util.HashMap;
43 import java.util.HashSet;
44 import java.util.Map;
45 import java.util.Set;
46 import java.util.stream.Collectors;
47 import java.util.zip.ZipEntry;
48 import java.util.zip.ZipFile;
49 import static java.lang.module.ModuleDescriptor.*;
50 import static build.tools.jigsaw.ModuleSummary.HtmlDocument.Selector.*;
51 import static build.tools.jigsaw.ModuleSummary.HtmlDocument.Division.*;
52
53 public class ModuleSummary {
54 private static final String USAGE = "Usage: ModuleSummary --module-path <dir> -o <outfile> [--root mn]*";
55
56 public static void main(String[] args) throws Exception {
57 int i=0;
58 Path modpath = null;
59 Path outfile = null;
60 Set<String> roots = new HashSet<>();
61 while (i < args.length && args[i].startsWith("-")) {
62 String arg = args[i++];
63 switch (arg) {
475 sb.append(toTableRow(String.format("Total jmod bytes (%d %s)", deps.size(), files), reqJmodFileSize));
476
477 if (aggregator && !aggregatorNote) {
478 aggregatorNote = true;
479 sb.append(blankRow());
480 sb.append(toTableRow("<i>* aggregator is a module with module-info.class only</i>", BR));
481 }
482 if (!totalBytesNote) {
483 totalBytesNote = true;
484 sb.append(blankRow());
485 sb.append(toTableRow("<i><sup>1</sup>sum of all files including debug files</i>", BR));
486 sb.append(toTableRow("<i><sup>2</sup>sum of direct and indirect dependencies</i>", BR));
487 }
488 sb.append("</table>").append("</td>");
489 return sb.toString();
490 }
491
492 private String moduleName(String mn) {
493 if (aggregator) {
494 StringBuilder sb = new StringBuilder();
495 sb.append(String.format("<tr><td colspan=\"2\"><span class=\"%s\">", AGGREGATOR))
496 .append(mn)
497 .append("</span>").append(" ");
498 if (!aggregatorNote) {
499 sb.append("(aggregator<sup>*</sup>)");
500 } else {
501 sb.append("(aggregator)");
502 }
503 sb.append("</td></tr>");
504 return sb.toString();
505 } else {
506 return toTableRow(mn, MODULE_DEF);
507 }
508 }
509
510 public String requiresColumn() {
511 StringBuilder sb = new StringBuilder();
512 sb.append(String.format("<td>"));
513 boolean footnote = requiresTransitiveNote;
514 ms.descriptor().requires().stream()
515 .sorted(Comparator.comparing(Requires::name))
535 sb.append("<i>+").append(indirectDeps).append(" transitive dependencies</i>");
536 }
537 if (footnote != requiresTransitiveNote) {
538 sb.append("<br><br>").append("<i>* bold denotes requires transitive</i>");
539 }
540 sb.append("</td>");
541 return sb.toString();
542 }
543
544 public String exportsColumn() {
545 StringBuilder sb = new StringBuilder();
546 sb.append(String.format(" <td class=\"%s\">", CODE));
547 ms.descriptor().exports().stream()
548 .sorted(Comparator.comparing(Exports::source))
549 .filter(e -> !e.isQualified())
550 .forEach(e -> sb.append(e.source()).append("<br>").append("\n"));
551 sb.append("</td>");
552 return sb.toString();
553 }
554
555 public String servicesColumn() {
556 StringBuilder sb = new StringBuilder();
557 sb.append(String.format(" <td class=\"%s\">", CODE));
558 ms.descriptor().uses().stream()
559 .sorted()
560 .forEach(s -> sb.append("uses ").append(s).append("<br>").append("\n"));
561 ms.descriptor().provides().stream()
562 .sorted(Comparator.comparing(Provides::service))
563 .map(p -> String.format("provides %s<br> with %s",
564 p.service(), p.providers()))
565 .forEach(p -> sb.append(p).append("<br>").append("\n"));
566 sb.append("</td>");
567 return sb.toString();
568 }
569
570 public String otherSectionColumn() {
571 StringBuilder sb = new StringBuilder();
572 sb.append("<td>");
573 sb.append(String.format("<table class=\"%s\">", MODULE)).append("\n");
574 // commands
575 if (ms.numCommands() > 0) {
576 sb.append(toTableRow("bin/", CODE));
577 ms.commands().entrySet().stream()
578 .sorted(Map.Entry.comparingByKey())
579 .forEach(e -> sb.append(toTableRow(e.getKey(), e.getValue(), CODE)));
580 sb.append(blankRow());
581 }
582
583 // native libraries
584 if (ms.numNativeLibraries() > 0) {
635 }
636 builder.data(bytes);
637 return builder.build();
638 }
639
640 class TableDataBuilder {
641 private final StringBuilder sb;
642 TableDataBuilder() {
643 this.sb = new StringBuilder("<tr>");
644 }
645 TableDataBuilder data(String s) {
646 data(BR, s);
647 return this;
648 }
649 TableDataBuilder data(long num) {
650 data(NUMBER, String.format("%,d", num));
651 return this;
652 }
653 TableDataBuilder colspan(Selector selector, int columns, String data) {
654 sb.append("<td colspan=\"").append(columns).append("\">");
655 sb.append("<span class=\"").append(selector).append("\">");
656 sb.append(data).append("</span></td>");
657 return this;
658 }
659
660 TableDataBuilder data(Selector selector, String data) {
661 sb.append("<td class=\"").append(selector).append("\">");
662 sb.append(data).append("</td>");
663 return this;
664 }
665 String build() {
666 sb.append("</tr>");
667 return sb.toString();
668 }
669 }
670 }
671
672 private static final String[] STYLES = new String[]{
673 "<link rel=\"stylesheet\" type=\"text/css\" href=\"/.fonts/dejavu.css\"/>",
674 "<style type=\"text/css\">",
675 " HTML, BODY, DIV, SPAN, APPLET, OBJECT, IFRAME, H1, H2, H3, H4, H5, H6, P,",
|
1 /*
2 * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 build.tools.jigsaw;
27
28 import java.io.IOException;
29 import java.io.PrintStream;
30 import java.lang.module.Configuration;
31 import java.lang.module.ModuleDescriptor;
32 import java.lang.module.ModuleFinder;
33 import java.lang.module.ModuleReference;
34 import java.lang.module.ResolvedModule;
35 import java.nio.file.Files;
36 import java.nio.file.Path;
37 import java.nio.file.Paths;
38 import java.util.Arrays;
39 import java.util.ArrayList;
40 import java.util.Comparator;
41 import java.util.Date;
42 import java.util.Enumeration;
43 import java.util.HashMap;
44 import java.util.HashSet;
45 import java.util.List;
46 import java.util.Map;
47 import java.util.Set;
48 import java.util.stream.Collectors;
49 import java.util.zip.ZipEntry;
50 import java.util.zip.ZipFile;
51 import static java.lang.module.ModuleDescriptor.*;
52 import static build.tools.jigsaw.ModuleSummary.HtmlDocument.Selector.*;
53 import static build.tools.jigsaw.ModuleSummary.HtmlDocument.Division.*;
54
55 public class ModuleSummary {
56 private static final String USAGE = "Usage: ModuleSummary --module-path <dir> -o <outfile> [--root mn]*";
57
58 public static void main(String[] args) throws Exception {
59 int i=0;
60 Path modpath = null;
61 Path outfile = null;
62 Set<String> roots = new HashSet<>();
63 while (i < args.length && args[i].startsWith("-")) {
64 String arg = args[i++];
65 switch (arg) {
477 sb.append(toTableRow(String.format("Total jmod bytes (%d %s)", deps.size(), files), reqJmodFileSize));
478
479 if (aggregator && !aggregatorNote) {
480 aggregatorNote = true;
481 sb.append(blankRow());
482 sb.append(toTableRow("<i>* aggregator is a module with module-info.class only</i>", BR));
483 }
484 if (!totalBytesNote) {
485 totalBytesNote = true;
486 sb.append(blankRow());
487 sb.append(toTableRow("<i><sup>1</sup>sum of all files including debug files</i>", BR));
488 sb.append(toTableRow("<i><sup>2</sup>sum of direct and indirect dependencies</i>", BR));
489 }
490 sb.append("</table>").append("</td>");
491 return sb.toString();
492 }
493
494 private String moduleName(String mn) {
495 if (aggregator) {
496 StringBuilder sb = new StringBuilder();
497 sb.append(String.format("<tr><td colspan=\"2\"><span class=\"%s\">", AGGREGATOR))
498 .append(mn)
499 .append("</span>").append(" ");
500 if (!aggregatorNote) {
501 sb.append("(aggregator<sup>*</sup>)");
502 } else {
503 sb.append("(aggregator)");
504 }
505 sb.append("</td></tr>");
506 return sb.toString();
507 } else {
508 return toTableRow(mn, MODULE_DEF);
509 }
510 }
511
512 public String requiresColumn() {
513 StringBuilder sb = new StringBuilder();
514 sb.append(String.format("<td>"));
515 boolean footnote = requiresTransitiveNote;
516 ms.descriptor().requires().stream()
517 .sorted(Comparator.comparing(Requires::name))
537 sb.append("<i>+").append(indirectDeps).append(" transitive dependencies</i>");
538 }
539 if (footnote != requiresTransitiveNote) {
540 sb.append("<br><br>").append("<i>* bold denotes requires transitive</i>");
541 }
542 sb.append("</td>");
543 return sb.toString();
544 }
545
546 public String exportsColumn() {
547 StringBuilder sb = new StringBuilder();
548 sb.append(String.format(" <td class=\"%s\">", CODE));
549 ms.descriptor().exports().stream()
550 .sorted(Comparator.comparing(Exports::source))
551 .filter(e -> !e.isQualified())
552 .forEach(e -> sb.append(e.source()).append("<br>").append("\n"));
553 sb.append("</td>");
554 return sb.toString();
555 }
556
557 private String providesEntry(Provides p) {
558 StringBuilder sb = new StringBuilder();
559 sb.append(String.format("provides %s<br>\n", p.service()));
560 List<String> pvs = new ArrayList<>(p.providers());
561 pvs.sort(Comparator.naturalOrder());
562 for (int i = 0; i < pvs.size(); i++) { // My kingdom for Stream::zip ...
563 String fmt = ((i == 0)
564 ? " with %s"
565 : ",<br> %s");
566 sb.append(String.format(fmt, pvs.get(i)));
567 }
568 sb.append("\n");
569 return sb.toString();
570 }
571
572 public String servicesColumn() {
573 StringBuilder sb = new StringBuilder();
574 sb.append(String.format(" <td class=\"%s\">", CODE));
575 ms.descriptor().uses().stream()
576 .sorted()
577 .forEach(s -> sb.append("uses ").append(s).append("<br>").append("\n"));
578 ms.descriptor().provides().stream()
579 .sorted(Comparator.comparing(Provides::service))
580 .map(this::providesEntry)
581 .forEach(p -> sb.append(p).append("<br>").append("\n"));
582 sb.append("</td>");
583 return sb.toString();
584 }
585
586 public String otherSectionColumn() {
587 StringBuilder sb = new StringBuilder();
588 sb.append("<td>");
589 sb.append(String.format("<table class=\"%s\">", MODULE)).append("\n");
590 // commands
591 if (ms.numCommands() > 0) {
592 sb.append(toTableRow("bin/", CODE));
593 ms.commands().entrySet().stream()
594 .sorted(Map.Entry.comparingByKey())
595 .forEach(e -> sb.append(toTableRow(e.getKey(), e.getValue(), CODE)));
596 sb.append(blankRow());
597 }
598
599 // native libraries
600 if (ms.numNativeLibraries() > 0) {
651 }
652 builder.data(bytes);
653 return builder.build();
654 }
655
656 class TableDataBuilder {
657 private final StringBuilder sb;
658 TableDataBuilder() {
659 this.sb = new StringBuilder("<tr>");
660 }
661 TableDataBuilder data(String s) {
662 data(BR, s);
663 return this;
664 }
665 TableDataBuilder data(long num) {
666 data(NUMBER, String.format("%,d", num));
667 return this;
668 }
669 TableDataBuilder colspan(Selector selector, int columns, String data) {
670 sb.append("<td colspan=\"").append(columns).append("\">");
671 sb.append("<span class=\"").append(selector).append("\">");
672 sb.append(data).append("</span></td>");
673 return this;
674 }
675
676 TableDataBuilder data(Selector selector, String data) {
677 sb.append("<td class=\"").append(selector).append("\">");
678 sb.append(data).append("</td>");
679 return this;
680 }
681 String build() {
682 sb.append("</tr>");
683 return sb.toString();
684 }
685 }
686 }
687
688 private static final String[] STYLES = new String[]{
689 "<link rel=\"stylesheet\" type=\"text/css\" href=\"/.fonts/dejavu.css\"/>",
690 "<style type=\"text/css\">",
691 " HTML, BODY, DIV, SPAN, APPLET, OBJECT, IFRAME, H1, H2, H3, H4, H5, H6, P,",
|