8153035: GenModuleInfoSource strips away the API comments
authormchung
Wed, 30 Mar 2016 17:23:45 -0700
changeset 36742 286b583dc969
parent 36741 aaf41d8104ce
child 36743 bdc3f1b79fb7
8153035: GenModuleInfoSource strips away the API comments Reviewed-by: chegar
jdk/make/src/classes/build/tools/module/GenModuleInfoSource.java
jdk/make/src/classes/build/tools/module/Module.java
jdk/make/src/classes/build/tools/module/ModuleInfoReader.java
jdk/make/src/classes/build/tools/module/ModulesXmlReader.java
jdk/make/src/classes/build/tools/module/ModulesXmlWriter.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<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();
-    }
-}