| /* |
| * 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. 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 jdk.internal.module; |
| |
| import java.lang.module.ModuleDescriptor; |
| import java.lang.module.ModuleDescriptor.Exports; |
| import java.lang.module.ModuleDescriptor.Opens; |
| import java.lang.module.ModuleDescriptor.Provides; |
| import java.lang.module.ModuleDescriptor.Requires; |
| import java.lang.module.ModuleDescriptor.Version; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Set; |
| |
| import jdk.internal.misc.JavaLangModuleAccess; |
| import jdk.internal.misc.SharedSecrets; |
| |
| /** |
| * This builder is optimized for reconstituting the {@code ModuleDescriptor}s |
| * for system modules. The validation should be done at jlink time. |
| * |
| * 1. skip name validation |
| * 2. ignores dependency hashes. |
| * 3. ModuleDescriptor skips the defensive copy and directly uses the |
| * sets/maps created in this Builder. |
| * |
| * SystemModules should contain modules for the boot layer. |
| */ |
| final class Builder { |
| private static final JavaLangModuleAccess JLMA = |
| SharedSecrets.getJavaLangModuleAccess(); |
| |
| // Static cache of the most recently seen Version to cheaply deduplicate |
| // most Version objects. JDK modules have the same version. |
| static Version cachedVersion; |
| |
| /** |
| * Returns a {@link Requires} for a dependence on a module with the given |
| * (and possibly empty) set of modifiers, and optionally the version |
| * recorded at compile time. |
| */ |
| public static Requires newRequires(Set<Requires.Modifier> mods, |
| String mn, |
| String compiledVersion) |
| { |
| Version version = null; |
| if (compiledVersion != null) { |
| // use the cached version if the same version string |
| Version ver = cachedVersion; |
| if (ver != null && compiledVersion.equals(ver.toString())) { |
| version = ver; |
| } else { |
| version = Version.parse(compiledVersion); |
| } |
| } |
| return JLMA.newRequires(mods, mn, version); |
| } |
| |
| /** |
| * Returns a {@link Requires} for a dependence on a module with the given |
| * (and possibly empty) set of modifiers, and optionally the version |
| * recorded at compile time. |
| */ |
| public static Requires newRequires(Set<Requires.Modifier> mods, |
| String mn) |
| { |
| return newRequires(mods, mn, null); |
| } |
| |
| /** |
| * Returns a {@link Exports} for a qualified export, with |
| * the given (and possibly empty) set of modifiers, |
| * to a set of target modules. |
| */ |
| public static Exports newExports(Set<Exports.Modifier> ms, |
| String pn, |
| Set<String> targets) { |
| return JLMA.newExports(ms, pn, targets); |
| } |
| |
| /** |
| * Returns an {@link Opens} for an unqualified open with a given set of |
| * modifiers. |
| */ |
| public static Opens newOpens(Set<Opens.Modifier> ms, String pn) { |
| return JLMA.newOpens(ms, pn); |
| } |
| |
| /** |
| * Returns an {@link Opens} for a qualified opens, with |
| * the given (and possibly empty) set of modifiers, |
| * to a set of target modules. |
| */ |
| public static Opens newOpens(Set<Opens.Modifier> ms, |
| String pn, |
| Set<String> targets) { |
| return JLMA.newOpens(ms, pn, targets); |
| } |
| |
| /** |
| * Returns a {@link Exports} for an unqualified export with a given set |
| * of modifiers. |
| */ |
| public static Exports newExports(Set<Exports.Modifier> ms, String pn) { |
| return JLMA.newExports(ms, pn); |
| } |
| |
| /** |
| * Returns a {@link Provides} for a service with a given list of |
| * implementation classes. |
| */ |
| public static Provides newProvides(String st, List<String> pcs) { |
| return JLMA.newProvides(st, pcs); |
| } |
| |
| final String name; |
| boolean open, synthetic, mandated; |
| Set<Requires> requires; |
| Set<Exports> exports; |
| Set<Opens> opens; |
| Set<String> packages; |
| Set<String> uses; |
| Set<Provides> provides; |
| Version version; |
| String mainClass; |
| |
| Builder(String name) { |
| this.name = name; |
| this.requires = Collections.emptySet(); |
| this.exports = Collections.emptySet(); |
| this.opens = Collections.emptySet(); |
| this.provides = Collections.emptySet(); |
| this.uses = Collections.emptySet(); |
| } |
| |
| Builder open(boolean value) { |
| this.open = value; |
| return this; |
| } |
| |
| Builder synthetic(boolean value) { |
| this.synthetic = value; |
| return this; |
| } |
| |
| Builder mandated(boolean value) { |
| this.mandated = value; |
| return this; |
| } |
| |
| /** |
| * Sets module exports. |
| */ |
| public Builder exports(Exports[] exports) { |
| this.exports = Set.of(exports); |
| return this; |
| } |
| |
| /** |
| * Sets module opens. |
| */ |
| public Builder opens(Opens[] opens) { |
| this.opens = Set.of(opens); |
| return this; |
| } |
| |
| /** |
| * Sets module requires. |
| */ |
| public Builder requires(Requires[] requires) { |
| this.requires = Set.of(requires); |
| return this; |
| } |
| |
| /** |
| * Adds a set of (possible empty) packages. |
| */ |
| public Builder packages(Set<String> packages) { |
| this.packages = packages; |
| return this; |
| } |
| |
| /** |
| * Sets the set of service dependences. |
| */ |
| public Builder uses(Set<String> uses) { |
| this.uses = uses; |
| return this; |
| } |
| |
| /** |
| * Sets module provides. |
| */ |
| public Builder provides(Provides[] provides) { |
| this.provides = Set.of(provides); |
| return this; |
| } |
| |
| /** |
| * Sets the module version. |
| * |
| * @throws IllegalArgumentException if {@code v} is null or cannot be |
| * parsed as a version string |
| * |
| * @see Version#parse(String) |
| */ |
| public Builder version(String v) { |
| Version ver = cachedVersion; |
| if (ver != null && v.equals(ver.toString())) { |
| version = ver; |
| } else { |
| cachedVersion = version = Version.parse(v); |
| } |
| return this; |
| } |
| |
| /** |
| * Sets the module main class. |
| */ |
| public Builder mainClass(String mc) { |
| mainClass = mc; |
| return this; |
| } |
| |
| /** |
| * Returns an immutable set of the module modifiers derived from the flags. |
| */ |
| private Set<ModuleDescriptor.Modifier> modifiers() { |
| int n = 0; |
| if (open) n++; |
| if (synthetic) n++; |
| if (mandated) n++; |
| if (n == 0) { |
| return Collections.emptySet(); |
| } else { |
| ModuleDescriptor.Modifier[] mods = new ModuleDescriptor.Modifier[n]; |
| if (open) mods[--n] = ModuleDescriptor.Modifier.OPEN; |
| if (synthetic) mods[--n] = ModuleDescriptor.Modifier.SYNTHETIC; |
| if (mandated) mods[--n] = ModuleDescriptor.Modifier.MANDATED; |
| return Set.of(mods); |
| } |
| } |
| |
| /** |
| * Builds a {@code ModuleDescriptor} from the components. |
| */ |
| public ModuleDescriptor build(int hashCode) { |
| assert name != null; |
| return JLMA.newModuleDescriptor(name, |
| version, |
| modifiers(), |
| requires, |
| exports, |
| opens, |
| uses, |
| provides, |
| packages, |
| mainClass, |
| hashCode); |
| } |
| } |