1 /* 2 * Copyright (c) 2015, 2016, 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.HashSet; 35 import java.util.List; 36 import java.util.Set; 37 38 import jdk.internal.misc.JavaLangModuleAccess; 39 import jdk.internal.misc.SharedSecrets; 40 41 /** 42 * This builder is optimized for reconstituting ModuleDescriptor 43 * for system modules. The validation should be done at jlink time. 44 * 45 * 1. skip name validation 46 * 2. ignores dependency hashes. 47 * 3. ModuleDescriptor skips the defensive copy and directly uses the 48 * sets/maps created in this Builder. 49 * 50 * SystemModules should contain modules for the boot layer. 51 */ 52 final class Builder { 53 private static final JavaLangModuleAccess JLMA = 54 SharedSecrets.getJavaLangModuleAccess(); 55 56 // Static cache of the most recently seen Version to cheaply deduplicate 57 // most Version objects. JDK modules have the same version. 58 static Version cachedVersion; 59 60 /** 61 * Returns a {@link Requires} for a dependence on a module with the given 62 * (and possibly empty) set of modifiers, and optionally the version 63 * recorded at compile time. 64 */ 65 public static Requires newRequires(Set<Requires.Modifier> mods, 66 String mn, 67 String compiledVersion) 68 { 69 Version version = null; 70 if (compiledVersion != null) { 71 // use the cached version if the same version string 72 Version ver = cachedVersion; 73 if (ver != null && compiledVersion.equals(ver.toString())) { 74 version = ver; 75 } else { 76 version = Version.parse(compiledVersion); 77 } 78 } 79 return JLMA.newRequires(mods, mn, version); 80 } 81 82 /** 83 * Returns a {@link Requires} for a dependence on a module with the given 84 * (and possibly empty) set of modifiers, and optionally the version 85 * recorded at compile time. 86 */ 87 public static Requires newRequires(Set<Requires.Modifier> mods, 88 String mn) 89 { 90 return newRequires(mods, mn, null); 91 } 92 93 /** 94 * Returns a {@link Exports} for a qualified export, with 95 * the given (and possibly empty) set of modifiers, 96 * to a set of target modules. 97 */ 98 public static Exports newExports(Set<Exports.Modifier> ms, 99 String pn, 100 Set<String> targets) { 101 return JLMA.newExports(ms, pn, targets); 102 } 103 104 /** 105 * Returns an {@link Opens} for an unqualified open with a given set of 106 * modifiers. 107 */ 108 public static Opens newOpens(Set<Opens.Modifier> ms, String pn) { 109 return JLMA.newOpens(ms, pn); 110 } 111 112 /** 113 * Returns an {@link Opens} for a qualified opens, with 114 * the given (and possibly empty) set of modifiers, 115 * to a set of target modules. 116 */ 117 public static Opens newOpens(Set<Opens.Modifier> ms, 118 String pn, 119 Set<String> targets) { 120 return JLMA.newOpens(ms, pn, targets); 121 } 122 123 /** 124 * Returns a {@link Exports} for an unqualified export with a given set 125 * of modifiers. 126 */ 127 public static Exports newExports(Set<Exports.Modifier> ms, String pn) { 128 return JLMA.newExports(ms, pn); 129 } 130 131 /** 132 * Returns a {@link Provides} for a service with a given list of 133 * implementation classes. 134 */ 135 public static Provides newProvides(String st, List<String> pcs) { 136 return JLMA.newProvides(st, pcs); 137 } 138 139 final String name; 140 boolean open; 141 boolean synthetic; 142 Set<Requires> requires; 143 Set<Exports> exports; 144 Set<Opens> opens; 145 Set<String> packages; 146 Set<String> uses; 147 Set<Provides> provides; 148 Version version; 149 String mainClass; 150 String osName; 151 String osArch; 152 String osVersion; 153 154 Builder(String name) { 155 this.name = name; 156 this.requires = Collections.emptySet(); 157 this.exports = Collections.emptySet(); 158 this.opens = Collections.emptySet(); 159 this.provides = Collections.emptySet(); 160 this.uses = Collections.emptySet(); 161 } 162 163 Builder open(boolean value) { 164 this.open = value; 165 return this; 166 } 167 168 Builder synthetic(boolean value) { 169 this.synthetic = 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 * Sets the OS name. 249 */ 250 public Builder osName(String name) { 251 this.osName = name; 252 return this; 253 } 254 255 /** 256 * Sets the OS arch. 257 */ 258 public Builder osArch(String arch) { 259 this.osArch = arch; 260 return this; 261 } 262 263 /** 264 * Sets the OS version. 265 * 266 * @throws IllegalStateException if already set 267 */ 268 public Builder osVersion(String version) { 269 this.osVersion = version; 270 return this; 271 } 272 273 /** 274 * Builds a {@code ModuleDescriptor} from the components. 275 */ 276 public ModuleDescriptor build(int hashCode) { 277 assert name != null; 278 279 Set<ModuleDescriptor.Modifier> modifiers; 280 if (open || synthetic) { 281 modifiers = new HashSet<>(); 282 if (open) modifiers.add(ModuleDescriptor.Modifier.OPEN); 283 if (synthetic) modifiers.add(ModuleDescriptor.Modifier.SYNTHETIC); 284 modifiers = Collections.unmodifiableSet(modifiers); 285 } else { 286 modifiers = Collections.emptySet(); 287 } 288 289 return JLMA.newModuleDescriptor(name, 290 version, 291 modifiers, 292 requires, 293 exports, 294 opens, 295 uses, 296 provides, 297 packages, 298 mainClass, 299 osName, 300 osArch, 301 osVersion, 302 hashCode); 303 } 304 }