| /* | |
| * Copyright (c) 2015, 2017, 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. | |
| * | |
| * 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 toolbox; | |
| import java.io.IOException; | |
| import java.nio.file.Files; | |
| import java.nio.file.Path; | |
| import java.nio.file.Paths; | |
| import java.util.ArrayList; | |
| import java.util.Arrays; | |
| import java.util.LinkedHashSet; | |
| import java.util.List; | |
| import java.util.Set; | |
| import java.util.stream.Collectors; | |
| /** | |
| * Builder for module declarations. | |
| */ | |
| public class ModuleBuilder { | |
| private final ToolBox tb; | |
| private final String name; | |
| private String comment = ""; | |
| private boolean open; | |
| private List<String> requires = new ArrayList<>(); | |
| private List<String> exports = new ArrayList<>(); | |
| private List<String> opens = new ArrayList<>(); | |
| private List<String> uses = new ArrayList<>(); | |
| private List<String> provides = new ArrayList<>(); | |
| private List<String> content = new ArrayList<>(); | |
| private Set<Path> modulePath = new LinkedHashSet<>(); | |
| /** | |
| * Creates a builder for a module. | |
| * @param tb a Toolbox that can be used to compile the module declaration | |
| * @param name the name of the module to be built | |
| */ | |
| public ModuleBuilder(ToolBox tb, String name) { | |
| this(tb, false, name); | |
| } | |
| /** | |
| * Creates a builder for a module. | |
| * @param tb a Toolbox that can be used to compile the module declaration | |
| * @param open whether or not this is an open module | |
| * @param name the name of the module to be built | |
| */ | |
| public ModuleBuilder(ToolBox tb, boolean open, String name) { | |
| this.tb = tb; | |
| this.open = open; | |
| this.name = name; | |
| } | |
| /** | |
| * Sets the doc comment for the declaration. | |
| * @param comment the content of the comment, excluding the initial | |
| * '/**', leading whitespace and asterisks, and the final trailing 'a;/'. | |
| * @return this builder | |
| */ | |
| public ModuleBuilder comment(String comment) { | |
| this.comment = comment; | |
| return this; | |
| } | |
| /** | |
| * Adds a "requires" directive to the declaration. | |
| * @param module the name of the module that is required | |
| * @param modulePath a path in while to locate the modules | |
| * if the declaration is compiled | |
| * @return this builder | |
| */ | |
| public ModuleBuilder requires(String module, Path... modulePath) { | |
| addDirective(requires, "requires " + module + ";"); | |
| this.modulePath.addAll(Arrays.asList(modulePath)); | |
| return this; | |
| } | |
| /** | |
| * Adds a "requires static" directive to the declaration. | |
| * @param module the name of the module that is required | |
| * @param modulePath a path in which to locate the modules | |
| * if the declaration is compiled | |
| * @return this builder | |
| */ | |
| public ModuleBuilder requiresStatic(String module, Path... modulePath) { | |
| addDirective(requires, "requires static " + module + ";"); | |
| this.modulePath.addAll(Arrays.asList(modulePath)); | |
| return this; | |
| } | |
| /** | |
| * Adds a "requires transitive" directive to the declaration. | |
| * @param module the name of the module that is required | |
| * @param modulePath a path in which to locate the modules | |
| * if the declaration is compiled | |
| * @return this builder | |
| */ | |
| public ModuleBuilder requiresTransitive(String module, Path... modulePath) { | |
| addDirective(requires, "requires transitive " + module + ";"); | |
| this.modulePath.addAll(Arrays.asList(modulePath)); | |
| return this; | |
| } | |
| /** | |
| * Adds a "requires static transitive" directive to the declaration. | |
| * @param module the name of the module that is required | |
| * @param modulePath a path in which to locate the modules | |
| * if the declaration is compiled | |
| * @return this builder | |
| */ | |
| public ModuleBuilder requiresStaticTransitive(String module, Path... modulePath) { | |
| addDirective(requires, "requires static transitive " + module + ";"); | |
| this.modulePath.addAll(Arrays.asList(modulePath)); | |
| return this; | |
| } | |
| /** | |
| * Adds an unqualified "exports" directive to the declaration. | |
| * @param pkg the name of the package to be exported | |
| * @return this builder | |
| */ | |
| public ModuleBuilder exports(String pkg) { | |
| return addDirective(exports, "exports " + pkg + ";"); | |
| } | |
| /** | |
| * Adds a qualified "exports" directive to the declaration. | |
| * @param pkg the name of the package to be exported | |
| * @param module the name of the module to which it is to be exported | |
| * @return this builder | |
| */ | |
| public ModuleBuilder exportsTo(String pkg, String module) { | |
| return addDirective(exports, "exports " + pkg + " to " + module + ";"); | |
| } | |
| /** | |
| * Adds an unqualified "opens" directive to the declaration. | |
| * @param pkg the name of the package to be opened | |
| * @return this builder | |
| */ | |
| public ModuleBuilder opens(String pkg) { | |
| return addDirective(opens, "opens " + pkg + ";"); | |
| } | |
| /** | |
| * Adds a qualified "opens" directive to the declaration. | |
| * @param pkg the name of the package to be opened | |
| * @param module the name of the module to which it is to be opened | |
| * @return this builder | |
| */ | |
| public ModuleBuilder opensTo(String pkg, String module) { | |
| return addDirective(opens, "opens " + pkg + " to " + module + ";"); | |
| } | |
| /** | |
| * Adds a "uses" directive to the declaration. | |
| * @param service the name of the service type | |
| * @return this builder | |
| */ | |
| public ModuleBuilder uses(String service) { | |
| return addDirective(uses, "uses " + service + ";"); | |
| } | |
| /** | |
| * Adds a "provides" directive to the declaration. | |
| * @param service the name of the service type | |
| * @param implementation the name of the implementation type | |
| * @return this builder | |
| */ | |
| public ModuleBuilder provides(String service, String implementation) { | |
| return addDirective(provides, "provides " + service + " with " + implementation + ";"); | |
| } | |
| private ModuleBuilder addDirective(List<String> directives, String directive) { | |
| directives.add(directive); | |
| return this; | |
| } | |
| /** | |
| * Adds type definitions to the module. | |
| * @param content a series of strings, each representing the content of | |
| * a compilation unit to be included with the module | |
| * @return this builder | |
| */ | |
| public ModuleBuilder classes(String... content) { | |
| this.content.addAll(Arrays.asList(content)); | |
| return this; | |
| } | |
| /** | |
| * Writes the module declaration and associated additional compilation | |
| * units to a module directory within a given directory. | |
| * @param srcDir the directory in which a directory will be created | |
| * to contain the source files for the module | |
| * @return the directory containing the source files for the module | |
| */ | |
| public Path write(Path srcDir) throws IOException { | |
| Files.createDirectories(srcDir); | |
| List<String> sources = new ArrayList<>(); | |
| StringBuilder sb = new StringBuilder(); | |
| if (!comment.isEmpty()) { | |
| sb.append("/**\n * ") | |
| .append(comment.replace("\n", "\n * ")) | |
| .append("\n */\n"); | |
| } | |
| if (open) { | |
| sb.append("open "); | |
| } | |
| sb.append("module ").append(name).append(" {\n"); | |
| requires.forEach(r -> sb.append(" " + r + "\n")); | |
| exports.forEach(e -> sb.append(" " + e + "\n")); | |
| opens.forEach(o -> sb.append(" " + o + "\n")); | |
| uses.forEach(u -> sb.append(" " + u + "\n")); | |
| provides.forEach(p -> sb.append(" " + p + "\n")); | |
| sb.append("}"); | |
| sources.add(sb.toString()); | |
| sources.addAll(content); | |
| Path moduleSrc = srcDir.resolve(name); | |
| tb.writeJavaFiles(moduleSrc, sources.toArray(new String[]{})); | |
| return moduleSrc; | |
| } | |
| /** | |
| * Writes the source files for the module to an interim directory, | |
| * and then compiles them to a given directory. | |
| * @param modules the directory in which a directory will be created | |
| * to contain the compiled class files for the module | |
| * @throws IOException if an error occurs while compiling the files | |
| */ | |
| public void build(Path modules) throws IOException { | |
| build(Paths.get(modules + "Src"), modules); | |
| } | |
| /** | |
| * Writes the source files for the module to a specified directory, | |
| * and then compiles them to a given directory. | |
| * @param src the directory in which a directory will be created | |
| * to contain the source files for the module | |
| * @param modules the directory in which a directory will be created | |
| * to contain the compiled class files for the module | |
| * @throws IOException if an error occurs while compiling the files | |
| */ | |
| public void build(Path src, Path modules) throws IOException { | |
| Path moduleSrc = write(src); | |
| String mp = modulePath.stream() | |
| .map(Path::toString) | |
| .collect(Collectors.joining(ToolBox.pathSeparator)); | |
| new JavacTask(tb) | |
| .outdir(Files.createDirectories(modules.resolve(name))) | |
| .options("--module-path", mp) | |
| .files(tb.findJavaFiles(moduleSrc)) | |
| .run() | |
| .writeAll(); | |
| } | |
| } |