| 1 | Backport from openjdk 10
|
| 2 |
|
| 3 | |
| 4 | |
| 5 | @@ -1,5 +1,5 @@
|
| 6 | /*
|
| 7 | - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
| 8 | + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
| 9 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
| 10 | *
|
| 11 | * This code is free software; you can redistribute it and/or modify it
|
| 12 | @@ -30,13 +30,16 @@
|
| 13 | import jdk.tools.jlink.plugin.ResourcePoolModuleView;
|
| 14 |
|
| 15 | import java.lang.module.ModuleDescriptor;
|
| 16 | +import java.lang.module.ModuleDescriptor.Requires;
|
| 17 | import java.lang.module.ModuleDescriptor.Requires.Modifier;
|
| 18 |
|
| 19 | import java.nio.ByteBuffer;
|
| 20 | -import java.util.Deque;
|
| 21 | +import java.util.ArrayList;
|
| 22 | +import java.util.Comparator;
|
| 23 | import java.util.HashMap;
|
| 24 | import java.util.HashSet;
|
| 25 | -import java.util.LinkedList;
|
| 26 | +import java.util.LinkedHashSet;
|
| 27 | +import java.util.List;
|
| 28 | import java.util.Map;
|
| 29 | import java.util.Set;
|
| 30 | import java.util.stream.Stream;
|
| 31 | @@ -45,9 +48,8 @@
|
| 32 | * Helper class to sort modules in topological order
|
| 33 | */
|
| 34 | public final class ModuleSorter {
|
| 35 | - private final Deque<ResourcePoolModule> nodes = new LinkedList<>();
|
| 36 | - private final Map<String, Set<ResourcePoolModule>> edges = new HashMap<>();
|
| 37 | - private final Deque<ResourcePoolModule> result = new LinkedList<>();
|
| 38 | + private final Map<ResourcePoolModule, Set<ResourcePoolModule>> graph = new HashMap<>();
|
| 39 | + private final List<ResourcePoolModule> result = new ArrayList<>();
|
| 40 |
|
| 41 | private final ResourcePoolModuleView moduleView;
|
| 42 |
|
| 43 | @@ -69,11 +71,17 @@
|
| 44 |
|
| 45 | private ModuleSorter addModule(ResourcePoolModule module) {
|
| 46 | addNode(module);
|
| 47 | - readModuleDescriptor(module).requires().forEach(req -> {
|
| 48 | + // the module graph will be traversed in a stable order for
|
| 49 | + // the topological sort. So add the dependences in the module name order
|
| 50 | + readModuleDescriptor(module).requires()
|
| 51 | + .stream()
|
| 52 | + .sorted(Comparator.comparing(Requires::name))
|
| 53 | + .forEach(req ->
|
| 54 | + {
|
| 55 | ResourcePoolModule dep = moduleView.findModule(req.name()).orElse(null);
|
| 56 | if (dep != null) {
|
| 57 | addNode(dep);
|
| 58 | - edges.get(module.name()).add(dep);
|
| 59 | + graph.get(module).add(dep);
|
| 60 | } else if (!req.modifiers().contains(Modifier.STATIC)) {
|
| 61 | throw new PluginException(req.name() + " not found");
|
| 62 | }
|
| 63 | @@ -82,22 +90,23 @@
|
| 64 | }
|
| 65 |
|
| 66 | private void addNode(ResourcePoolModule module) {
|
| 67 | - nodes.add(module);
|
| 68 | - edges.computeIfAbsent(module.name(), _n -> new HashSet<>());
|
| 69 | + graph.computeIfAbsent(module, _n -> new LinkedHashSet<>());
|
| 70 | }
|
| 71 |
|
| 72 | + /*
|
| 73 | + * The module graph will be traversed in a stable order
|
| 74 | + * (traversing the modules and their dependences in alphabetical order)
|
| 75 | + * so that it will produce the same result of a given module graph.
|
| 76 | + */
|
| 77 | private synchronized void build() {
|
| 78 | - if (!result.isEmpty() || nodes.isEmpty())
|
| 79 | + if (!result.isEmpty() || graph.isEmpty())
|
| 80 | return;
|
| 81 |
|
| 82 | - Deque<ResourcePoolModule> visited = new LinkedList<>();
|
| 83 | - Deque<ResourcePoolModule> done = new LinkedList<>();
|
| 84 | - ResourcePoolModule node;
|
| 85 | - while ((node = nodes.poll()) != null) {
|
| 86 | - if (!visited.contains(node)) {
|
| 87 | - visit(node, visited, done);
|
| 88 | - }
|
| 89 | - }
|
| 90 | + Set<ResourcePoolModule> visited = new HashSet<>();
|
| 91 | + Set<ResourcePoolModule> done = new HashSet<>();
|
| 92 | + graph.keySet().stream()
|
| 93 | + .sorted(Comparator.comparing(ResourcePoolModule::name))
|
| 94 | + .forEach(node -> visit(node, visited, done));
|
| 95 | }
|
| 96 |
|
| 97 | public Stream<ResourcePoolModule> sorted() {
|
| 98 | @@ -106,19 +115,21 @@
|
| 99 | }
|
| 100 |
|
| 101 | private void visit(ResourcePoolModule node,
|
| 102 | - Deque<ResourcePoolModule> visited,
|
| 103 | - Deque<ResourcePoolModule> done) {
|
| 104 | + Set<ResourcePoolModule> visited,
|
| 105 | + Set<ResourcePoolModule> done) {
|
| 106 | if (visited.contains(node)) {
|
| 107 | if (!done.contains(node)) {
|
| 108 | throw new IllegalArgumentException("Cyclic detected: " +
|
| 109 | - node + " " + edges.get(node.name()));
|
| 110 | + node + " " + graph.get(node));
|
| 111 | }
|
| 112 | return;
|
| 113 | }
|
| 114 | +
|
| 115 | + // traverse the dependences of the given module which are
|
| 116 | + // also sorted in alphabetical order
|
| 117 | visited.add(node);
|
| 118 | - edges.get(node.name())
|
| 119 | - .forEach(x -> visit(x, visited, done));
|
| 120 | + graph.get(node).forEach(x -> visit(x, visited, done));
|
| 121 | done.add(node);
|
| 122 | - result.addLast(node);
|
| 123 | + result.add(node);
|
| 124 | }
|
| 125 | }
|