# HG changeset patch # User mchung # Date 1459383825 25200 # Node ID 286b583dc969dc6193733b3f3bc4ac6d2ce08b52 # Parent aaf41d8104ce9fdb3998680001e2c3ab8abdc1e7 8153035: GenModuleInfoSource strips away the API comments Reviewed-by: chegar diff -r aaf41d8104ce -r 286b583dc969 jdk/make/src/classes/build/tools/module/GenModuleInfoSource.java --- 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> 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 exports = new HashSet<>(); + private final Map> exportsTo = new HashMap<>(); + private final Set uses = new HashSet<>(); + private final Map> 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 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> 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 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); + } } diff -r aaf41d8104ce -r 286b583dc969 jdk/make/src/classes/build/tools/module/Module.java --- 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 { - 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 requires; - private final Map> exports; - private final Set uses; - private final Map> provides; - - private Module(String name, - Set requires, - Map> exports, - Set uses, - Map> 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 requires() { - return requires; - } - - public Map> exports() { - return exports; - } - - public Set uses() { - return uses; - } - - public Map> 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 requires = new HashSet<>(); - final Map> exports = new HashMap<>(); - final Set uses = new HashSet<>(); - final Map> 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 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 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 s1 = m2.exports().get(pn); - Set 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"; - } - } -} diff -r aaf41d8104ce -r 286b583dc969 jdk/make/src/classes/build/tools/module/ModuleInfoReader.java --- 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 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> 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 + " "); - } - } - } -} diff -r aaf41d8104ce -r 286b583dc969 jdk/make/src/classes/build/tools/module/ModulesXmlReader.java --- 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 readModules(Path modulesXml) - throws XMLStreamException, IOException - { - Set modules = new HashSet<>(); - try (InputStream in = new BufferedInputStream(Files.newInputStream(modulesXml))) { - Set 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 load(InputStream in) - throws XMLStreamException, IOException - { - Set modules = new HashSet<>(); - XMLInputFactory factory = XMLInputFactory.newInstance(); - XMLEventReader stream = factory.createXMLEventReader(in); - Module.Builder mb = null; - String modulename = null; - String pkg = null; - Set 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); - } -} diff -r aaf41d8104ce -r 286b583dc969 jdk/make/src/classes/build/tools/module/ModulesXmlWriter.java --- 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 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 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 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(); - } -}