/* |
|
* 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); |
|
} |
|
} |