1 /* 2 * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package jdk.internal.module; 26 27 import java.lang.module.ModuleDescriptor; 28 import java.lang.module.ModuleDescriptor.Exports; 29 import java.lang.module.ModuleDescriptor.Opens; 30 import java.lang.module.ModuleDescriptor.Provides; 31 import java.lang.module.ModuleDescriptor.Requires; 32 import java.lang.module.ModuleDescriptor.Version; 33 import java.util.Collections; 34 import java.util.List; 35 import java.util.Set; 36 37 import jdk.internal.access.JavaLangModuleAccess; 38 import jdk.internal.access.SharedSecrets; 39 40 /** 41 * This builder is optimized for reconstituting the {@code ModuleDescriptor}s 42 * for system modules. The validation should be done at jlink time. 43 * 44 * 1. skip name validation 45 * 2. ignores dependency hashes. 46 * 3. ModuleDescriptor skips the defensive copy and directly uses the 47 * sets/maps created in this Builder. 48 * 49 * SystemModules should contain modules for the boot layer. 50 */ 51 final class Builder { 52 private static final JavaLangModuleAccess JLMA = 53 SharedSecrets.getJavaLangModuleAccess(); 54 55 // Static cache of the most recently seen Version to cheaply deduplicate 56 // most Version objects. JDK modules have the same version. 57 static Version cachedVersion; 58 59 /** 60 * Returns a {@link Requires} for a dependence on a module with the given 61 * (and possibly empty) set of modifiers, and optionally the version 62 * recorded at compile time. 63 */ 64 public static Requires newRequires(Set<Requires.Modifier> mods, 65 String mn, 66 String compiledVersion) 67 { 68 Version version = null; 69 if (compiledVersion != null) { 70 // use the cached version if the same version string 71 Version ver = cachedVersion; 72 if (ver != null && compiledVersion.equals(ver.toString())) { 73 version = ver; 74 } else { 75 version = Version.parse(compiledVersion); 76 } 77 } 78 return JLMA.newRequires(mods, mn, version); 79 } 80 81 /** 82 * Returns a {@link Requires} for a dependence on a module with the given 83 * (and possibly empty) set of modifiers, and optionally the version 84 * recorded at compile time. 85 */ 86 public static Requires newRequires(Set<Requires.Modifier> mods, 87 String mn) 88 { 89 return newRequires(mods, mn, null); 90 } 91 92 /** 93 * Returns a {@link Exports} for a qualified export, with 94 * the given (and possibly empty) set of modifiers, 95 * to a set of target modules. 96 */ 97 public static Exports newExports(Set<Exports.Modifier> ms, 98 String pn, 99 Set<String> targets) { 100 return JLMA.newExports(ms, pn, targets); 101 } 102 103 /** 104 * Returns an {@link Opens} for an unqualified open with a given set of 105 * modifiers. 106 */ 107 public static Opens newOpens(Set<Opens.Modifier> ms, String pn) { 108 return JLMA.newOpens(ms, pn); 109 } 110 111 /** 112 * Returns an {@link Opens} for a qualified opens, with 113 * the given (and possibly empty) set of modifiers, 114 * to a set of target modules. 115 */ 116 public static Opens newOpens(Set<Opens.Modifier> ms, 117 String pn, 118 Set<String> targets) { 119 return JLMA.newOpens(ms, pn, targets); 120 } 121 122 /** 123 * Returns a {@link Exports} for an unqualified export with a given set 124 * of modifiers. 125 */ 126 public static Exports newExports(Set<Exports.Modifier> ms, String pn) { 127 return JLMA.newExports(ms, pn); 128 } 129 130 /** 131 * Returns a {@link Provides} for a service with a given list of 132 * implementation classes. 133 */ 134 public static Provides newProvides(String st, List<String> pcs) { 135 return JLMA.newProvides(st, pcs); 136 } 137 138 final String name; 139 boolean open, synthetic, mandated; 140 Set<Requires> requires; 141 Set<Exports> exports; 142 Set<Opens> opens; 143 Set<String> packages; 144 Set<String> uses; 145 Set<Provides> provides; 146 Version version; 147 String mainClass; 148 149 Builder(String name) { 150 this.name = name; 151 this.requires = Collections.emptySet(); 152 this.exports = Collections.emptySet(); 153 this.opens = Collections.emptySet(); 154 this.provides = Collections.emptySet(); 155 this.uses = Collections.emptySet(); 156 } 157 158 Builder open(boolean value) { 159 this.open = value; 160 return this; 161 } 162 163 Builder synthetic(boolean value) { 164 this.synthetic = value; 165 return this; 166 } 167 168 Builder mandated(boolean value) { 169 this.mandated = value; 170 return this; 171 } 172 173 /** 174 * Sets module exports. 175 */ 176 public Builder exports(Exports[] exports) { 177 this.exports = Set.of(exports); 178 return this; 179 } 180 181 /** 182 * Sets module opens. 183 */ 184 public Builder opens(Opens[] opens) { 185 this.opens = Set.of(opens); 186 return this; 187 } 188 189 /** 190 * Sets module requires. 191 */ 192 public Builder requires(Requires[] requires) { 193 this.requires = Set.of(requires); 194 return this; 195 } 196 197 /** 198 * Adds a set of (possible empty) packages. 199 */ 200 public Builder packages(Set<String> packages) { 201 this.packages = packages; 202 return this; 203 } 204 205 /** 206 * Sets the set of service dependences. 207 */ 208 public Builder uses(Set<String> uses) { 209 this.uses = uses; 210 return this; 211 } 212 213 /** 214 * Sets module provides. 215 */ 216 public Builder provides(Provides[] provides) { 217 this.provides = Set.of(provides); 218 return this; 219 } 220 221 /** 222 * Sets the module version. 223 * 224 * @throws IllegalArgumentException if {@code v} is null or cannot be 225 * parsed as a version string 226 * 227 * @see Version#parse(String) 228 */ 229 public Builder version(String v) { 230 Version ver = cachedVersion; 231 if (ver != null && v.equals(ver.toString())) { 232 version = ver; 233 } else { 234 cachedVersion = version = Version.parse(v); 235 } 236 return this; 237 } 238 239 /** 240 * Sets the module main class. 241 */ 242 public Builder mainClass(String mc) { 243 mainClass = mc; 244 return this; 245 } 246 247 /** 248 * Returns an immutable set of the module modifiers derived from the flags. 249 */ 250 private Set<ModuleDescriptor.Modifier> modifiers() { 251 int n = 0; 252 if (open) n++; 253 if (synthetic) n++; 254 if (mandated) n++; 255 if (n == 0) { 256 return Collections.emptySet(); 257 } else { 258 ModuleDescriptor.Modifier[] mods = new ModuleDescriptor.Modifier[n]; 259 if (open) mods[--n] = ModuleDescriptor.Modifier.OPEN; 260 if (synthetic) mods[--n] = ModuleDescriptor.Modifier.SYNTHETIC; 261 if (mandated) mods[--n] = ModuleDescriptor.Modifier.MANDATED; 262 return Set.of(mods); 263 } 264 } 265 266 /** 267 * Builds a {@code ModuleDescriptor} from the components. 268 */ 269 public ModuleDescriptor build(int hashCode) { 270 assert name != null; 271 return JLMA.newModuleDescriptor(name, 272 version, 273 modifiers(), 274 requires, 275 exports, 276 opens, 277 uses, 278 provides, 279 packages, 280 mainClass, 281 hashCode); 282 } 283 }