GenGraphs.java revision 16735:3534a97c9244
1/*
2 * Copyright (c) 2014, 2017, 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
26package build.tools.jigsaw;
27
28import com.sun.tools.jdeps.ModuleDotGraph;
29import com.sun.tools.jdeps.ModuleDotGraph.DotGraphBuilder;
30
31import java.io.IOException;
32import java.lang.module.Configuration;
33import java.lang.module.ModuleDescriptor;
34import java.lang.module.ModuleFinder;
35import java.lang.module.ModuleReference;
36import java.nio.file.Files;
37import java.nio.file.Path;
38import java.nio.file.Paths;
39import java.util.HashMap;
40import java.util.HashSet;
41import java.util.Map;
42import java.util.Set;
43
44/**
45 * Generate the DOT file for a module graph for each module in the JDK
46 * after transitive reduction.
47 */
48public class GenGraphs {
49
50    public static void main(String[] args) throws Exception {
51        Path dir = null;
52        boolean spec = false;
53        for (int i=0; i < args.length; i++) {
54            String arg = args[i];
55            if (arg.equals("--spec")) {
56                spec = true;
57            } else if (arg.equals("--output")) {
58                i++;
59                dir = i < args.length ? Paths.get(args[i]) : null;
60            } else if (arg.startsWith("-")) {
61                throw new IllegalArgumentException("Invalid option: " + arg);
62            }
63        }
64
65        if (dir == null) {
66            System.err.println("ERROR: must specify --output argument");
67            System.exit(1);
68        }
69
70        // setup and configure the dot graph attributes
71        initDotGraphAttributes();
72        Files.createDirectories(dir);
73
74        GenGraphs genGraphs = new GenGraphs(dir, spec);
75
76        // print dot file for each module
77        Map<String, Configuration> configurations = new HashMap<>();
78        Set<String> modules = new HashSet<>();
79        ModuleFinder finder = ModuleFinder.ofSystem();
80        for (ModuleReference mref : finder.findAll()) {
81            String name = (mref.descriptor().name());
82            modules.add(name);
83            if (genGraphs.accept(name, mref.descriptor())) {
84                configurations.put(name, Configuration.empty()
85                                                      .resolve(finder,
86                                                               ModuleFinder.of(),
87                                                               Set.of(name)));
88            }
89        }
90
91        if (genGraphs.accept("jdk", null)) {
92            // print a graph of all JDK modules
93            configurations.put("jdk", Configuration.empty()
94                                                   .resolve(finder,
95                                                            ModuleFinder.of(),
96                                                            modules));
97        }
98
99        genGraphs.genDotFiles(configurations);
100    }
101
102    static void initDotGraphAttributes() {
103        int h = 1000;
104        DotGraphBuilder.weight("java.se", "java.sql.rowset", h * 10);
105        DotGraphBuilder.weight("java.sql.rowset", "java.sql", h * 10);
106        DotGraphBuilder.weight("java.sql", "java.xml", h * 10);
107        DotGraphBuilder.weight("java.xml", "java.base", h * 10);
108
109        DotGraphBuilder.sameRankNodes(Set.of("java.logging", "java.scripting", "java.xml"));
110        DotGraphBuilder.sameRankNodes(Set.of("java.sql"));
111        DotGraphBuilder.sameRankNodes(Set.of("java.compiler", "java.instrument"));
112        DotGraphBuilder.sameRankNodes(Set.of("java.desktop", "java.management"));
113        DotGraphBuilder.sameRankNodes(Set.of("java.corba", "java.xml.ws"));
114        DotGraphBuilder.sameRankNodes(Set.of("java.xml.bind", "java.xml.ws.annotation"));
115        DotGraphBuilder.setRankSep(0.7);
116        DotGraphBuilder.setFontSize(12);
117        DotGraphBuilder.setArrowSize(1);
118        DotGraphBuilder.setArrowWidth(2);
119    }
120
121    private final Path dir;
122    private final boolean spec;
123    GenGraphs(Path dir, boolean spec) {
124        this.dir = dir;
125        this.spec = spec;
126    }
127
128    void genDotFiles(Map<String, Configuration> configurations) throws IOException {
129        ModuleDotGraph dotGraph = new ModuleDotGraph(configurations, spec);
130        dotGraph.genDotFiles(dir);
131    }
132
133    boolean accept(String name, ModuleDescriptor descriptor) {
134        if (!spec) return true;
135
136        if (name.equals("jdk"))
137            return false;
138
139        if (name.equals("java.se") || name.equals("java.se.ee"))
140            return true;
141
142        // only the module that has exported API
143        return descriptor.exports().stream()
144                         .filter(e -> !e.isQualified())
145                         .findAny().isPresent();
146    }
147}