--- a/jdk/make/src/classes/build/tools/module/GenModuleInfoSource.java Wed Mar 30 19:56:34 2016 +0100
+++ b/jdk/make/src/classes/build/tools/module/GenModuleInfoSource.java Wed Mar 30 17:23:45 2016 -0700
@@ -25,25 +25,27 @@
package build.tools.module;
import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
+import java.util.stream.Collectors;
/**
- * A build tool to extend the module-info.java in the source tree
- * for platform-specific exports, uses, and provides and write
- * to the specified output file.
+ * A build tool to extend the module-info.java in the source tree for
+ * platform-specific exports, uses, and provides and write to the specified
+ * output file. Injecting platform-specific requires is not supported.
*
- * GenModulesList build tool currently generates the modules.list from
- * the module-info.java from the source tree that will be used for
- * the make target and dependences.
- *
- * The build currently invokes gensrc-$MODULE.gmk after modules.list
- * is generated. Hence, platform-specific requires is not supported.
+ * The extra exports, uses, provides can be specified in module-info.java.extra
+ * files and GenModuleInfoSource will be invoked for each module that has
+ * module-info.java.extra in the source directory.
*/
public class GenModuleInfoSource {
private final static String USAGE =
@@ -57,17 +59,32 @@
public static void main(String... args) throws Exception {
Path outfile = null;
Path moduleInfoJava = null;
- Map<String, Set<String>> options = new HashMap<>();
+ GenModuleInfoSource genModuleInfo = new GenModuleInfoSource();
// validate input arguments
for (int i = 0; i < args.length; i++){
String option = args[i];
if (option.startsWith("-")) {
String arg = args[++i];
- if (option.equals("-exports") ||
- option.equals("-uses") ||
- option.equals("-provides")) {
- options.computeIfAbsent(option, _k -> new HashSet<>()).add(arg);
+ if (option.equals("-exports")) {
+ int index = arg.indexOf('/');
+ if (index > 0) {
+ String pn = arg.substring(0, index);
+ String mn = arg.substring(index + 1, arg.length());
+ genModuleInfo.exportTo(pn, mn);
+ } else {
+ genModuleInfo.export(arg);
+ }
+ } else if (option.equals("-uses")) {
+ genModuleInfo.use(arg);
+ } else if (option.equals("-provides")) {
+ int index = arg.indexOf('/');
+ if (index <= 0) {
+ throw new IllegalArgumentException("invalid -provide argument: " + arg);
+ }
+ String service = arg.substring(0, index);
+ String impl = arg.substring(index + 1, arg.length());
+ genModuleInfo.provide(service, impl);
} else if (option.equals("-o")) {
outfile = Paths.get(arg);
} else {
@@ -87,48 +104,145 @@
System.err.println(USAGE);
System.exit(-1);
}
- // read module-info.java
- Module.Builder builder = ModuleInfoReader.builder(moduleInfoJava);
- augment(builder, options);
// generate new module-info.java
- Module module = builder.build();
+ genModuleInfo.generate(moduleInfoJava, outfile);
+ }
+
+ private final Set<String> exports = new HashSet<>();
+ private final Map<String, Set<String>> exportsTo = new HashMap<>();
+ private final Set<String> uses = new HashSet<>();
+ private final Map<String, Set<String>> provides = new HashMap<>();
+ GenModuleInfoSource() {
+ }
+
+ private void export(String p) {
+ Objects.requireNonNull(p);
+ if (exports.contains(p) || exportsTo.containsKey(p)) {
+ throw new RuntimeException("duplicated exports: " + p);
+ }
+ exports.add(p);
+ }
+ private void exportTo(String p, String mn) {
+ Objects.requireNonNull(p);
+ Objects.requireNonNull(mn);
+ if (exports.contains(p)) {
+ throw new RuntimeException("unqualified exports already exists: " + p);
+ }
+ exportsTo.computeIfAbsent(p, _k -> new HashSet<>()).add(mn);
+ }
+
+ private void use(String service) {
+ uses.add(service);
+ }
+
+ private void provide(String s, String impl) {
+ provides.computeIfAbsent(s, _k -> new HashSet<>()).add(impl);
+ }
+
+ private void generate(Path sourcefile, Path outfile) throws IOException {
Path parent = outfile.getParent();
if (parent != null)
Files.createDirectories(parent);
- try (BufferedWriter writer = Files.newBufferedWriter(outfile)) {
- writer.write(module.toString());
- }
- }
+ List<String> lines = Files.readAllLines(sourcefile);
+ try (BufferedWriter bw = Files.newBufferedWriter(outfile);
+ PrintWriter writer = new PrintWriter(bw)) {
+ int lineNumber = 0;
+ for (String l : lines) {
+ lineNumber++;
+ String[] s = l.trim().split("\\s+");
+ String keyword = s[0].trim();
+ int nextIndex = keyword.length();
+ String exp = null;
+ int n = l.length();
+ switch (keyword) {
+ case "exports":
+ boolean inExportsTo = false;
+ // assume package name immediately after exports
+ exp = s[1].trim();
+ if (s.length >= 3) {
+ nextIndex = l.indexOf(exp, nextIndex) + exp.length();
+ if (s[2].trim().equals("to")) {
+ inExportsTo = true;
+ n = l.indexOf("to", nextIndex) + "to".length();
+ } else {
+ throw new RuntimeException(sourcefile + ", line " +
+ lineNumber + ", is malformed: " + s[2]);
+ }
+ }
- private static void augment(Module.Builder builder, Map<String, Set<String>> options) {
- for (String opt : options.keySet()) {
- if (opt.equals("-exports")) {
- for (String arg : options.get(opt)) {
- int index = arg.indexOf('/');
- if (index > 0) {
- String pn = arg.substring(0, index);
- String mn = arg.substring(index + 1, arg.length());
- builder.exportTo(pn, mn);
- } else {
- builder.export(arg);
- }
- }
- } else if (opt.equals("-uses")) {
- options.get(opt).stream()
- .forEach(builder::use);
- } else if (opt.equals("-provides")) {
- for (String arg : options.get(opt)) {
- int index = arg.indexOf('/');
- if (index <= 0) {
- throw new IllegalArgumentException("invalid -provide argument: " + arg);
- }
- String service = arg.substring(0, index);
- String impl = arg.substring(index + 1, arg.length());
- builder.provide(service, impl);
+ // inject the extra targets after "to"
+ if (inExportsTo) {
+ writer.println(injectExportTargets(exp, l, n));
+ } else {
+ writer.println(l);
+ }
+ break;
+ case "to":
+ if (exp == null) {
+ throw new RuntimeException(sourcefile + ", line " +
+ lineNumber + ", is malformed");
+ }
+ n = l.indexOf("to", nextIndex) + "to".length();
+ writer.println(injectExportTargets(exp, l, n));
+ break;
+ case "}":
+ doAugments(writer);
+ // fall through
+ default:
+ writer.println(l);
+ // reset exports
+ exp = null;
}
}
}
}
+
+ private String injectExportTargets(String pn, String exp, int pos) {
+ Set<String> targets = exportsTo.remove(pn);
+ if (targets != null) {
+ StringBuilder sb = new StringBuilder();
+ // inject the extra targets after the given pos
+ sb.append(exp.substring(0, pos))
+ .append("\n\t")
+ .append(targets.stream()
+ .collect(Collectors.joining(",", "", ",")))
+ .append(" /* injected */");
+ if (pos < exp.length()) {
+ // print the remaining statement followed "to"
+ sb.append("\n\t")
+ .append(exp.substring(pos+1, exp.length()));
+ }
+ return sb.toString();
+ } else {
+ return exp;
+ }
+ }
+
+ private void doAugments(PrintWriter writer) {
+ if ((exports.size() + exportsTo.size() + uses.size() + provides.size()) == 0)
+ return;
+
+ writer.println(" // augmented from module-info.java.extra");
+ exports.stream()
+ .sorted()
+ .forEach(e -> writer.format(" exports %s;%n", e));
+ // remaining injected qualified exports
+ exportsTo.entrySet().stream()
+ .sorted(Map.Entry.comparingByKey())
+ .map(e -> String.format(" exports %s to%n%s;", e.getKey(),
+ e.getValue().stream().sorted()
+ .map(mn -> String.format(" %s", mn))
+ .collect(Collectors.joining(",\n"))))
+ .forEach(writer::println);
+ uses.stream().sorted()
+ .forEach(s -> writer.format(" uses %s;%n", s));
+ provides.entrySet().stream()
+ .sorted(Map.Entry.comparingByKey())
+ .flatMap(e -> e.getValue().stream().sorted()
+ .map(impl -> String.format(" provides %s with %s;",
+ e.getKey(), impl)))
+ .forEach(writer::println);
+ }
}
--- a/jdk/make/src/classes/build/tools/module/Module.java Wed Mar 30 19:56:34 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,280 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package build.tools.module;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-public class Module {
- public static class Dependence implements Comparable<Dependence> {
- final String name;
- final boolean reexport;
- Dependence(String name) {
- this(name, false);
- }
- Dependence(String name, boolean reexport) {
- this.name = name;
- this.reexport = reexport;
- }
-
- public String name() {
- return name;
- }
-
- public boolean reexport(){
- return reexport;
- }
-
- @Override
- public int hashCode() {
- int hash = 5;
- hash = 11 * hash + Objects.hashCode(this.name);
- hash = 11 * hash + (this.reexport ? 1 : 0);
- return hash;
- }
-
- public boolean equals(Object o) {
- Dependence d = (Dependence)o;
- return this.name.equals(d.name) && this.reexport == d.reexport;
- }
-
- @Override
- public int compareTo(Dependence o) {
- int rc = this.name.compareTo(o.name);
- return rc != 0 ? rc : Boolean.compare(this.reexport, o.reexport);
- }
-
- @Override
- public String toString() {
- return String.format("requires %s%s;",
- reexport ? "public " : "", name);
- }
- }
- private final String moduleName;
- private final Set<Dependence> requires;
- private final Map<String, Set<String>> exports;
- private final Set<String> uses;
- private final Map<String, Set<String>> provides;
-
- private Module(String name,
- Set<Dependence> requires,
- Map<String, Set<String>> exports,
- Set<String> uses,
- Map<String, Set<String>> provides) {
- this.moduleName = name;
- this.requires = Collections.unmodifiableSet(requires);
- this.exports = Collections.unmodifiableMap(exports);
- this.uses = Collections.unmodifiableSet(uses);
- this.provides = Collections.unmodifiableMap(provides);
- }
-
- public String name() {
- return moduleName;
- }
-
- public Set<Dependence> requires() {
- return requires;
- }
-
- public Map<String, Set<String>> exports() {
- return exports;
- }
-
- public Set<String> uses() {
- return uses;
- }
-
- public Map<String, Set<String>> provides() {
- return provides;
- }
-
- @Override
- public boolean equals(Object ob) {
- if (!(ob instanceof Module)) {
- return false;
- }
- Module that = (Module) ob;
- return (moduleName.equals(that.moduleName)
- && requires.equals(that.requires)
- && exports.equals(that.exports));
- }
-
- @Override
- public int hashCode() {
- int hc = moduleName.hashCode();
- hc = hc * 43 + requires.hashCode();
- hc = hc * 43 + exports.hashCode();
- return hc;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append(String.format("module %s {%n", moduleName));
- requires.stream()
- .sorted()
- .map(d -> String.format(" requires %s%s;%n", d.reexport ? "public " : "", d.name))
- .forEach(sb::append);
- exports.entrySet().stream()
- .filter(e -> e.getValue().isEmpty())
- .sorted(Map.Entry.comparingByKey())
- .map(e -> String.format(" exports %s;%n", e.getKey()))
- .forEach(sb::append);
- exports.entrySet().stream()
- .filter(e -> !e.getValue().isEmpty())
- .sorted(Map.Entry.comparingByKey())
- .map(e -> String.format(" exports %s to%n%s;%n", e.getKey(),
- e.getValue().stream().sorted()
- .map(mn -> String.format(" %s", mn))
- .collect(Collectors.joining(",\n"))))
- .forEach(sb::append);
- uses.stream().sorted()
- .map(s -> String.format(" uses %s;%n", s))
- .forEach(sb::append);
- provides.entrySet().stream()
- .sorted(Map.Entry.comparingByKey())
- .flatMap(e -> e.getValue().stream().sorted()
- .map(impl -> String.format(" provides %s with %s;%n", e.getKey(), impl)))
- .forEach(sb::append);
- sb.append("}").append("\n");
- return sb.toString();
- }
-
- /**
- * Module Builder
- */
- static class Builder {
- private String name;
- final Set<Dependence> requires = new HashSet<>();
- final Map<String, Set<String>> exports = new HashMap<>();
- final Set<String> uses = new HashSet<>();
- final Map<String, Set<String>> provides = new HashMap<>();
-
- public Builder() {
- }
-
- public Builder name(String n) {
- name = n;
- return this;
- }
-
- public Builder require(String d, boolean reexport) {
- requires.add(new Dependence(d, reexport));
- return this;
- }
-
- public Builder export(String p) {
- Objects.requireNonNull(p);
- if (exports.containsKey(p)) {
- throw new RuntimeException(name + " already exports " + p +
- " " + exports.get(p));
- }
- return exportTo(p, Collections.emptySet());
- }
-
- public Builder exportTo(String p, String mn) {
- Objects.requireNonNull(p);
- Objects.requireNonNull(mn);
- Set<String> ms = exports.get(p);
- if (ms != null && ms.isEmpty()) {
- throw new RuntimeException(name + " already has unqualified exports " + p);
- }
- exports.computeIfAbsent(p, _k -> new HashSet<>()).add(mn);
- return this;
- }
-
- public Builder exportTo(String p, Set<String> ms) {
- Objects.requireNonNull(p);
- Objects.requireNonNull(ms);
- if (exports.containsKey(p)) {
- throw new RuntimeException(name + " already exports " + p +
- " " + exports.get(p));
- }
- exports.put(p, new HashSet<>(ms));
- return this;
- }
-
- public Builder use(String cn) {
- uses.add(cn);
- return this;
- }
-
- public Builder provide(String s, String impl) {
- provides.computeIfAbsent(s, _k -> new HashSet<>()).add(impl);
- return this;
- }
-
- public Builder merge(Module m1, Module m2) {
- if (!m1.name().equals(m2.name())) {
- throw new IllegalArgumentException(m1.name() + " != " + m2.name());
- }
- name = m1.name();
- // ## reexports
- requires.addAll(m1.requires());
- requires.addAll(m2.requires());
- Stream.concat(m1.exports().keySet().stream(), m2.exports().keySet().stream())
- .distinct()
- .forEach(pn -> {
- Set<String> s1 = m2.exports().get(pn);
- Set<String> s2 = m2.exports().get(pn);
- if (s1 == null || s2 == null) {
- exportTo(pn, s1 != null ? s1 : s2);
- } else if (s1.isEmpty() || s2.isEmpty()) {
- // unqualified exports
- export(pn);
- } else {
- exportTo(pn, Stream.concat(s1.stream(), s2.stream())
- .collect(Collectors.toSet()));
- }
- });
- uses.addAll(m1.uses());
- uses.addAll(m2.uses());
- m1.provides().keySet().stream()
- .forEach(s -> m1.provides().get(s).stream()
- .forEach(impl -> provide(s, impl)));
- m2.provides().keySet().stream()
- .forEach(s -> m2.provides().get(s).stream()
- .forEach(impl -> provide(s, impl)));
- return this;
- }
-
- public Module build() {
- Module m = new Module(name, requires, exports, uses, provides);
- return m;
- }
-
- @Override
- public String toString() {
- return name != null ? name : "Unknown";
- }
- }
-}
--- a/jdk/make/src/classes/build/tools/module/ModuleInfoReader.java Wed Mar 30 19:56:34 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,357 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package build.tools.module;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.List;
-import java.util.function.Supplier;
-import java.util.regex.Pattern;
-import java.util.stream.Stream;
-
-import build.tools.module.Module.Builder;
-
-/**
- * Source reader of module-info.java
- */
-public class ModuleInfoReader {
- private final Path sourcefile;
- private final Builder builder;
- private ModuleInfoReader(Path file) {
- this.sourcefile = file;
- this.builder = new Builder();
- }
-
- public static Builder builder(Path file) throws IOException {
- ModuleInfoReader reader = new ModuleInfoReader(file);
- reader.readFile();
- return reader.builder;
- }
-
- /**
- * Reads the source file.
- */
- void readFile() throws IOException {
- List<String> lines = Files.readAllLines(sourcefile);
- boolean done = false;
- int lineNumber = 0;
- boolean inBlockComment = false;
- boolean inRequires = false;
- boolean reexports = false;
- boolean inProvides = false;
- boolean inWith = false;
- String serviceIntf = null;
- String providerClass = null;
- boolean inUses = false;
- boolean inExports = false;
- boolean inExportsTo = false;
- String qualifiedExports = null;
- Counter counter = new Counter();
-
- for (String line : lines) {
- lineNumber++;
- if (inBlockComment) {
- int c = line.indexOf("*/");
- if (c >= 0) {
- line = line.substring(c + 2, line.length());
- inBlockComment = false;
- } else {
- // skip lines until end of comment block
- continue;
- }
- }
- inBlockComment = beginBlockComment(line);
-
- line = trimComment(line).trim();
- // ignore empty lines
- if (line.length() == 0) {
- continue;
- }
- String values;
- if (inRequires || inExports | inUses | (inWith && providerClass == null)) {
- values = line;
- } else {
- String[] s = line.split("\\s+");
- String keyword = s[0].trim();
- int nextIndex = keyword.length();
- switch (keyword) {
- case "module":
- if (s.length != 3 || !s[2].trim().equals("{")) {
- throw new RuntimeException(sourcefile + ", line " +
- lineNumber + ", is malformed");
- }
- builder.name(s[1].trim());
- continue; // next line
- case "requires":
- inRequires = true;
- counter.numRequires++;
- if (s.length >= 2) {
- String ss = s[1].trim();
- if (ss.equals("public")) {
- nextIndex = line.indexOf(ss) + ss.length();
- reexports = true;
- }
- }
- break;
- case "exports":
- inExports = true;
- inExportsTo = false;
- counter.numExports++;
- qualifiedExports = null;
- if (s.length >= 3) {
- qualifiedExports = s[1].trim();
- nextIndex = line.indexOf(qualifiedExports, nextIndex)
- + qualifiedExports.length();
- if (s[2].trim().equals("to")) {
- inExportsTo = true;
- nextIndex = line.indexOf("to", nextIndex) + "to".length();
- } else {
- throw new RuntimeException(sourcefile + ", line " +
- lineNumber + ", is malformed: " + s[2]);
- }
- }
- break;
- case "to":
- if (!inExports || qualifiedExports == null) {
- throw new RuntimeException(sourcefile + ", line " +
- lineNumber + ", is malformed");
- }
- inExportsTo = true;
- break;
- case "uses":
- inUses = true;
- counter.numUses++;
- break;
- case "provides":
- inProvides = true;
- inWith = false;
- counter.numProvides++;
- serviceIntf = null;
- providerClass = null;
- if (s.length >= 2) {
- serviceIntf = s[1].trim();
- nextIndex = line.indexOf(serviceIntf) + serviceIntf.length();
- }
- if (s.length >= 3) {
- if (s[2].trim().equals("with")) {
- inWith = true;
- nextIndex = line.indexOf("with") + "with".length();
- } else {
- throw new RuntimeException(sourcefile + ", line " +
- lineNumber + ", is malformed: " + s[2]);
- }
- }
- break;
- case "with":
- if (!inProvides || serviceIntf == null) {
- throw new RuntimeException(sourcefile + ", line " +
- lineNumber + ", is malformed");
- }
- inWith = true;
- nextIndex = line.indexOf("with") + "with".length();
- break;
- case "}":
- counter.validate(builder);
- done = true;
- continue; // next line
- default:
- throw new RuntimeException(sourcefile + ", \"" +
- keyword + "\" on line " +
- lineNumber + ", is not recognized");
- }
- values = line.substring(nextIndex, line.length()).trim();
- }
-
- int len = values.length();
- if (len == 0) {
- continue; // next line
- }
- char lastchar = values.charAt(len - 1);
- if (lastchar != ',' && lastchar != ';') {
- throw new RuntimeException(sourcefile + ", line " +
- lineNumber + ", is malformed:" +
- " ',' or ';' is missing.");
- }
-
- values = values.substring(0, len - 1).trim();
- // parse the values specified for a keyword specified
- for (String s : values.split(",")) {
- s = s.trim();
- if (s.length() > 0) {
- if (inRequires) {
- if (builder.requires.contains(s)) {
- throw new RuntimeException(sourcefile + ", line "
- + lineNumber + " duplicated requires: \"" + s + "\"");
- }
- builder.require(s, reexports);
- } else if (inExports) {
- if (!inExportsTo && qualifiedExports == null) {
- builder.export(s);
- } else {
- builder.exportTo(qualifiedExports, s);
- }
- } else if (inUses) {
- builder.use(s);
- } else if (inProvides) {
- if (!inWith) {
- serviceIntf = s;
- } else {
- providerClass = s;
- builder.provide(serviceIntf, providerClass);
- }
- }
- }
- }
- if (lastchar == ';') {
- inRequires = false;
- reexports = false;
- inExports = false;
- inExportsTo = false;
- inProvides = false;
- inWith = false;
- inUses = false;
- }
- }
-
- if (inBlockComment) {
- throw new RuntimeException(sourcefile + ", line " +
- lineNumber + ", missing \"*/\" to end a block comment");
- }
- if (!done) {
- throw new RuntimeException(sourcefile + ", line " +
- lineNumber + ", missing \"}\" to end module definition" +
- " for \"" + builder + "\"");
- }
- return;
- }
-
- // the naming convention for the module names without dashes
- private static final Pattern CLASS_NAME_PATTERN = Pattern.compile("[\\w\\.\\*_$/]+");
- private static boolean beginBlockComment(String line) {
- int pos = 0;
- while (pos >= 0 && pos < line.length()) {
- int c = line.indexOf("/*", pos);
- if (c < 0) {
- return false;
- }
-
- if (c > 0 && !Character.isWhitespace(line.charAt(c - 1))) {
- return false;
- }
-
- int c1 = line.indexOf("//", pos);
- if (c1 >= 0 && c1 < c) {
- return false;
- }
-
- int c2 = line.indexOf("*/", c + 2);
- if (c2 < 0) {
- return true;
- }
- pos = c + 2;
- }
- return false;
- }
- private static String trimComment(String line) {
- StringBuilder sb = new StringBuilder();
-
- int pos = 0;
- while (pos >= 0 && pos < line.length()) {
- int c1 = line.indexOf("//", pos);
- if (c1 > 0 && !Character.isWhitespace(line.charAt(c1 - 1))) {
- // not a comment
- c1 = -1;
- }
-
- int c2 = line.indexOf("/*", pos);
- if (c2 > 0 && !Character.isWhitespace(line.charAt(c2 - 1))) {
- // not a comment
- c2 = -1;
- }
-
- int c = line.length();
- int n = line.length();
- if (c1 >= 0 || c2 >= 0) {
- if (c1 >= 0) {
- c = c1;
- }
- if (c2 >= 0 && c2 < c) {
- c = c2;
- }
- int c3 = line.indexOf("*/", c2 + 2);
- if (c == c2 && c3 > c2) {
- n = c3 + 2;
- }
- }
- if (c > 0) {
- if (sb.length() > 0) {
- // add a whitespace if multiple comments on one line
- sb.append(" ");
- }
- sb.append(line.substring(pos, c));
- }
- pos = n;
- }
- return sb.toString();
- }
-
-
- static class Counter {
- int numRequires;
- int numExports;
- int numUses;
- int numProvides;
-
- void validate(Builder builder) {
- assertEquals("requires", numRequires, builder.requires.size(),
- () -> builder.requires.stream()
- .map(Module.Dependence::toString));
- assertEquals("exports", numExports, builder.exports.size(),
- () -> builder.exports.entrySet().stream()
- .map(e -> "exports " + e.getKey() + " to " + e.getValue()));
- assertEquals("uses", numUses, builder.uses.size(),
- () -> builder.uses.stream());
- assertEquals("provides", numProvides,
- (int)builder.provides.values().stream()
- .flatMap(s -> s.stream())
- .count(),
- () -> builder.provides.entrySet().stream()
- .map(e -> "provides " + e.getKey() + " with " + e.getValue()));
- }
-
- private static void assertEquals(String msg, int expected, int got,
- Supplier<Stream<String>> supplier) {
- if (expected != got){
- System.err.println("ERROR: mismatched " + msg +
- " expected: " + expected + " got: " + got );
- supplier.get().sorted()
- .forEach(System.err::println);
- throw new AssertionError("mismatched " + msg +
- " expected: " + expected + " got: " + got + " ");
- }
- }
- }
-}
--- a/jdk/make/src/classes/build/tools/module/ModulesXmlReader.java Wed Mar 30 19:56:34 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,162 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package build.tools.module;
-
-import javax.xml.namespace.QName;
-import javax.xml.stream.XMLEventReader;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.events.Attribute;
-import javax.xml.stream.events.XMLEvent;
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.HashSet;
-import java.util.Set;
-
-public class ModulesXmlReader {
-
- private ModulesXmlReader() {}
-
- public static Set<Module> readModules(Path modulesXml)
- throws XMLStreamException, IOException
- {
- Set<Module> modules = new HashSet<>();
- try (InputStream in = new BufferedInputStream(Files.newInputStream(modulesXml))) {
- Set<Module> mods = ModulesXmlReader.load(in);
- modules.addAll(mods);
- }
- return modules;
- }
-
- private static final String MODULES = "modules";
- private static final String MODULE = "module";
- private static final String NAME = "name";
- private static final String DEPEND = "depend";
- private static final String EXPORT = "export";
- private static final String TO = "to";
- private static final QName REEXPORTS = new QName("re-exports");
- private static Set<Module> load(InputStream in)
- throws XMLStreamException, IOException
- {
- Set<Module> modules = new HashSet<>();
- XMLInputFactory factory = XMLInputFactory.newInstance();
- XMLEventReader stream = factory.createXMLEventReader(in);
- Module.Builder mb = null;
- String modulename = null;
- String pkg = null;
- Set<String> permits = new HashSet<>();
- while (stream.hasNext()) {
- XMLEvent event = stream.nextEvent();
- if (event.isStartElement()) {
- String startTag = event.asStartElement().getName().getLocalPart();
- switch (startTag) {
- case MODULES:
- break;
- case MODULE:
- if (mb != null) {
- throw new RuntimeException("end tag for module is missing");
- }
- modulename = getNextTag(stream, NAME);
- mb = new Module.Builder();
- mb.name(modulename);
- break;
- case NAME:
- throw new RuntimeException(event.toString());
- case DEPEND:
- boolean reexports = false;
- Attribute attr = event.asStartElement().getAttributeByName(REEXPORTS);
- if (attr != null) {
- String value = attr.getValue();
- if (value.equals("true") || value.equals("false")) {
- reexports = Boolean.parseBoolean(value);
- } else {
- throw new RuntimeException("unexpected attribute " + attr.toString());
- }
- }
- mb.require(getData(stream), reexports);
- break;
- case EXPORT:
- pkg = getNextTag(stream, NAME);
- break;
- case TO:
- permits.add(getData(stream));
- break;
- default:
- }
- } else if (event.isEndElement()) {
- String endTag = event.asEndElement().getName().getLocalPart();
- switch (endTag) {
- case MODULE:
- modules.add(mb.build());
- mb = null;
- break;
- case EXPORT:
- if (pkg == null) {
- throw new RuntimeException("export-to is malformed");
- }
- mb.exportTo(pkg, permits);
- pkg = null;
- permits.clear();
- break;
- default:
- }
- } else if (event.isCharacters()) {
- String s = event.asCharacters().getData();
- if (!s.trim().isEmpty()) {
- throw new RuntimeException("export-to is malformed");
- }
- }
- }
- return modules;
- }
-
- private static String getData(XMLEventReader reader)
- throws XMLStreamException
- {
- XMLEvent e = reader.nextEvent();
- if (e.isCharacters())
- return e.asCharacters().getData();
-
- throw new RuntimeException(e.toString());
- }
-
- private static String getNextTag(XMLEventReader reader, String tag)
- throws XMLStreamException
- {
- XMLEvent e = reader.nextTag();
- if (e.isStartElement()) {
- String t = e.asStartElement().getName().getLocalPart();
- if (!tag.equals(t)) {
- throw new RuntimeException(e + " expected: " + tag);
- }
- return getData(reader);
- }
- throw new RuntimeException("export-to name is missing:" + e);
- }
-}
--- a/jdk/make/src/classes/build/tools/module/ModulesXmlWriter.java Wed Mar 30 19:56:34 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,176 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package build.tools.module;
-
-import javax.xml.namespace.QName;
-import javax.xml.stream.XMLOutputFactory;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamWriter;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Map;
-import java.util.Set;
-
-public final class ModulesXmlWriter {
-
- private ModulesXmlWriter() {}
-
- public static void writeModules(Set<Module> modules, Path path)
- throws IOException, XMLStreamException
- {
- writeXML(modules, path);
- }
-
- private static final String MODULES = "modules";
- private static final String MODULE = "module";
- private static final String NAME = "name";
- private static final String DEPEND = "depend";
- private static final String EXPORT = "export";
- private static final String TO = "to";
- private static final QName REEXPORTS = new QName("re-exports");
-
- private static void writeXML(Set<Module> modules, Path path)
- throws IOException, XMLStreamException
- {
- XMLOutputFactory xof = XMLOutputFactory.newInstance();
- try (OutputStream out = Files.newOutputStream(path)) {
- int depth = 0;
- XMLStreamWriter xtw = xof.createXMLStreamWriter(out, "UTF-8");
- xtw.writeStartDocument("utf-8","1.0");
- writeStartElement(xtw, MODULES, depth);
- modules.stream()
- .sorted(Comparator.comparing(Module::name))
- .forEach(m -> writeModuleElement(xtw, m, depth+1));
- writeEndElement(xtw, depth);
- xtw.writeCharacters("\n");
- xtw.writeEndDocument();
- xtw.flush();
- xtw.close();
- }
- }
-
- private static void writeElement(XMLStreamWriter xtw,
- String element,
- String value,
- int depth) {
- try {
- writeStartElement(xtw, element, depth);
- xtw.writeCharacters(value);
- xtw.writeEndElement();
- } catch (XMLStreamException e) {
- throw new RuntimeException(e);
- }
- }
-
- private static void writeDependElement(XMLStreamWriter xtw,
- Module.Dependence d,
- int depth) {
- try {
- writeStartElement(xtw, DEPEND, depth);
- if (d.reexport) {
- xtw.writeAttribute("re-exports", "true");
- }
- xtw.writeCharacters(d.name);
- xtw.writeEndElement();
- } catch (XMLStreamException e) {
- throw new RuntimeException(e);
- }
- }
-
- private static void writeExportElement(XMLStreamWriter xtw,
- String pkg,
- int depth) {
- writeExportElement(xtw, pkg, Collections.emptySet(), depth);
- }
-
- private static void writeExportElement(XMLStreamWriter xtw,
- String pkg,
- Set<String> permits,
- int depth) {
- try {
- writeStartElement(xtw, EXPORT, depth);
- writeElement(xtw, NAME, pkg, depth+1);
- if (!permits.isEmpty()) {
- permits.stream().sorted()
- .forEach(m -> writeElement(xtw, TO, m, depth + 1));
- }
- writeEndElement(xtw, depth);
- } catch (XMLStreamException e) {
- throw new RuntimeException(e);
- }
- }
- private static void writeModuleElement(XMLStreamWriter xtw,
- Module m,
- int depth) {
- try {
- writeStartElement(xtw, MODULE, depth);
- writeElement(xtw, NAME, m.name(), depth+1);
- m.requires().stream().sorted(Comparator.comparing(d -> d.name))
- .forEach(d -> writeDependElement(xtw, d, depth+1));
- m.exports().keySet().stream()
- .filter(pn -> m.exports().get(pn).isEmpty())
- .sorted()
- .forEach(pn -> writeExportElement(xtw, pn, depth+1));
- m.exports().entrySet().stream()
- .filter(e -> !e.getValue().isEmpty())
- .sorted(Map.Entry.comparingByKey())
- .forEach(e -> writeExportElement(xtw, e.getKey(), e.getValue(), depth+1));
- writeEndElement(xtw, depth);
- } catch (XMLStreamException e) {
- throw new RuntimeException(e);
-
- }
- }
-
- /** Two spaces; the default indentation. */
- public static final String DEFAULT_INDENT = " ";
-
- /** stack[depth] indicates what's been written into the current scope. */
- private static String[] stack = new String[] { "\n",
- "\n" + DEFAULT_INDENT,
- "\n" + DEFAULT_INDENT + DEFAULT_INDENT,
- "\n" + DEFAULT_INDENT + DEFAULT_INDENT + DEFAULT_INDENT};
-
- private static void writeStartElement(XMLStreamWriter xtw,
- String name,
- int depth)
- throws XMLStreamException
- {
- xtw.writeCharacters(stack[depth]);
- xtw.writeStartElement(name);
- }
-
- private static void writeEndElement(XMLStreamWriter xtw, int depth)
- throws XMLStreamException
- {
- xtw.writeCharacters(stack[depth]);
- xtw.writeEndElement();
- }
-}