1 /* 2 * Copyright (c) 2015, 2017, 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.misc.JavaLangModuleAccess; 38 import jdk.internal.misc.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 String osName; 149 String osArch; 150 String osVersion; 151 152 Builder(String name) { 153 this.name = name; 154 this.requires = Collections.emptySet(); 155 this.exports = Collections.emptySet(); 156 this.opens = Collections.emptySet(); 157 this.provides = Collections.emptySet(); 158 this.uses = Collections.emptySet(); 159 } 160 161 Builder open(boolean value) { 162 this.open = value; 163 return this; 164 } 165 166 Builder synthetic(boolean value) { 167 this.synthetic = value; 168 return this; 169 } 170 171 Builder mandated(boolean value) { 172 this.mandated = value; 173 return this; 174 } 175 176 /** 177 * Sets module exports. 178 */ 179 public Builder exports(Exports[] exports) { 180 this.exports = Set.of(exports); 181 return this; 182 } 183 184 /** 185 * Sets module opens. 186 */ 187 public Builder opens(Opens[] opens) { 188 this.opens = Set.of(opens); 189 return this; 190 } 191 192 /** 193 * Sets module requires. 194 */ 195 public Builder requires(Requires[] requires) { 196 this.requires = Set.of(requires); 197 return this; 198 } 199 200 /** 201 * Adds a set of (possible empty) packages. 202 */ 203 public Builder packages(Set<String> packages) { 204 this.packages = packages; 205 return this; 206 } 207 208 /** 209 * Sets the set of service dependences. 210 */ 211 public Builder uses(Set<String> uses) { 212 this.uses = uses; 213 return this; 214 } 215 216 /** 217 * Sets module provides. 218 */ 219 public Builder provides(Provides[] provides) { 220 this.provides = Set.of(provides); 221 return this; 222 } 223 224 /** 225 * Sets the module version. 226 * 227 * @throws IllegalArgumentException if {@code v} is null or cannot be 228 * parsed as a version string 229 * 230 * @see Version#parse(String) 231 */ 232 public Builder version(String v) { 233 Version ver = cachedVersion; 234 if (ver != null && v.equals(ver.toString())) { 235 version = ver; 236 } else { 237 cachedVersion = version = Version.parse(v); 238 } 239 return this; 240 } 241 242 /** 243 * Sets the module main class. 244 */ 245 public Builder mainClass(String mc) { 246 mainClass = mc; 247 return this; 248 } 249 250 /** 251 * Sets the OS name. 252 */ 253 public Builder osName(String name) { 254 this.osName = name; 255 return this; 256 } 257 258 /** 259 * Sets the OS arch. 260 */ 261 public Builder osArch(String arch) { 262 this.osArch = arch; 263 return this; 264 } 265 266 /** 267 * Sets the OS version. 268 */ 269 public Builder osVersion(String version) { 270 this.osVersion = version; 271 return this; 272 } 273 274 /** 275 * Returns an immutable set of the module modifiers derived from the flags. 276 */ 277 private Set<ModuleDescriptor.Modifier> modifiers() { 278 int n = 0; 279 if (open) n++; 280 if (synthetic) n++; 281 if (mandated) n++; 282 if (n == 0) { 283 return Collections.emptySet(); 284 } else { 285 ModuleDescriptor.Modifier[] mods = new ModuleDescriptor.Modifier[n]; 286 if (open) mods[--n] = ModuleDescriptor.Modifier.OPEN; 287 if (synthetic) mods[--n] = ModuleDescriptor.Modifier.SYNTHETIC; 288 if (mandated) mods[--n] = ModuleDescriptor.Modifier.MANDATED; 289 return Set.of(mods); 290 } 291 } 292 293 /** 294 * Builds a {@code ModuleDescriptor} from the components. 295 */ 296 public ModuleDescriptor build(int hashCode) { 297 assert name != null; 298 return JLMA.newModuleDescriptor(name, 299 version, 300 modifiers(), 301 requires, 302 exports, 303 opens, 304 uses, 305 provides, 306 packages, 307 mainClass, 308 osName, 309 osArch, 310 osVersion, 311 hashCode); 312 } 313 }