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.List; 34 import java.util.Set; 35 36 import jdk.internal.access.JavaLangModuleAccess; 37 import jdk.internal.access.SharedSecrets; 38 39 /** 40 * This builder is optimized for reconstituting the {@code ModuleDescriptor}s 41 * for system modules. The validation should be done at jlink time. 42 * 43 * 1. skip name validation 44 * 2. ignores dependency hashes. 45 * 3. ModuleDescriptor skips the defensive copy and directly uses the 46 * sets/maps created in this Builder. 47 * 48 * SystemModules should contain modules for the boot layer. 49 */ 50 final class Builder { 51 private static final JavaLangModuleAccess JLMA = 52 SharedSecrets.getJavaLangModuleAccess(); 53 54 // Static cache of the most recently seen Version to cheaply deduplicate 55 // most Version objects. JDK modules have the same version. 56 static Version cachedVersion; 57 58 /** 59 * Returns a {@link Requires} for a dependence on a module with the given 60 * (and possibly empty) set of modifiers, and optionally the version 61 * recorded at compile time. 62 */ 63 public static Requires newRequires(Set<Requires.Modifier> mods, 64 String mn, 65 String compiledVersion) 66 { 67 Version version = null; 68 if (compiledVersion != null) { 69 // use the cached version if the same version string 70 Version ver = cachedVersion; 71 if (ver != null && compiledVersion.equals(ver.toString())) { 72 version = ver; 73 } else { 74 version = Version.parse(compiledVersion); 75 } 76 } 77 return JLMA.newRequires(mods, mn, version); 78 } 79 80 /** 81 * Returns a {@link Requires} for a dependence on a module with the given 82 * (and possibly empty) set of modifiers, and optionally the version 83 * recorded at compile time. 84 */ 85 public static Requires newRequires(Set<Requires.Modifier> mods, 86 String mn) 87 { 88 return newRequires(mods, mn, null); 89 } 90 91 /** 92 * Returns a {@link Exports} for a qualified export, with 93 * the given (and possibly empty) set of modifiers, 94 * to a set of target modules. 95 */ 96 public static Exports newExports(Set<Exports.Modifier> ms, 97 String pn, 98 Set<String> targets) { 99 return JLMA.newExports(ms, pn, targets); 100 } 101 102 /** 103 * Returns an {@link Opens} for an unqualified open with a given set of 104 * modifiers. 105 */ 106 public static Opens newOpens(Set<Opens.Modifier> ms, String pn) { 107 return JLMA.newOpens(ms, pn); 108 } 109 110 /** 111 * Returns an {@link Opens} for a qualified opens, with 112 * the given (and possibly empty) set of modifiers, 113 * to a set of target modules. 114 */ 115 public static Opens newOpens(Set<Opens.Modifier> ms, 116 String pn, 117 Set<String> targets) { 118 return JLMA.newOpens(ms, pn, targets); 119 } 120 121 /** 122 * Returns a {@link Exports} for an unqualified export with a given set 123 * of modifiers. 124 */ 125 public static Exports newExports(Set<Exports.Modifier> ms, String pn) { 126 return JLMA.newExports(ms, pn); 127 } 128 129 /** 130 * Returns a {@link Provides} for a service with a given list of 131 * implementation classes. 132 */ 133 public static Provides newProvides(String st, List<String> pcs) { 134 return JLMA.newProvides(st, pcs); 135 } 136 137 final String name; 138 boolean open, synthetic, mandated; 139 Set<Requires> requires; 140 Set<Exports> exports; 141 Set<Opens> opens; 142 Set<String> packages; 143 Set<String> uses; 144 Set<Provides> provides; 145 Version version; 146 String mainClass; 147 148 Builder(String name) { 149 this.name = name; 150 this.requires = Set.of(); 151 this.exports = Set.of(); 152 this.opens = Set.of(); 153 this.provides = Set.of(); 154 this.uses = Set.of(); 155 } 156 157 Builder open(boolean value) { 158 this.open = value; 159 return this; 160 } 161 162 Builder synthetic(boolean value) { 163 this.synthetic = value; 164 return this; 165 } 166 167 Builder mandated(boolean value) { 168 this.mandated = value; 169 return this; 170 } 171 172 /** 173 * Sets module exports. 174 */ 175 public Builder exports(Exports[] exports) { 176 this.exports = Set.of(exports); 177 return this; 178 } 179 180 /** 181 * Sets module opens. 182 */ 183 public Builder opens(Opens[] opens) { 184 this.opens = Set.of(opens); 185 return this; 186 } 187 188 /** 189 * Sets module requires. 190 */ 191 public Builder requires(Requires[] requires) { 192 this.requires = Set.of(requires); 193 return this; 194 } 195 196 /** 197 * Adds a set of (possible empty) packages. 198 */ 199 public Builder packages(Set<String> packages) { 200 this.packages = packages; 201 return this; 202 } 203 204 /** 205 * Sets the set of service dependences. 206 */ 207 public Builder uses(Set<String> uses) { 208 this.uses = uses; 209 return this; 210 } 211 212 /** 213 * Sets module provides. 214 */ 215 public Builder provides(Provides[] provides) { 216 this.provides = Set.of(provides); 217 return this; 218 } 219 220 /** 221 * Sets the module version. 222 * 223 * @throws IllegalArgumentException if {@code v} is null or cannot be 224 * parsed as a version string 225 * 226 * @see Version#parse(String) 227 */ 228 public Builder version(String v) { 229 Version ver = cachedVersion; 230 if (ver != null && v.equals(ver.toString())) { 231 version = ver; 232 } else { 233 cachedVersion = version = Version.parse(v); 234 } 235 return this; 236 } 237 238 /** 239 * Sets the module main class. 240 */ 241 public Builder mainClass(String mc) { 242 mainClass = mc; 243 return this; 244 } 245 246 /** 247 * Returns an immutable set of the module modifiers derived from the flags. 248 */ 249 private Set<ModuleDescriptor.Modifier> modifiers() { 250 int n = 0; 251 if (open) n++; 252 if (synthetic) n++; 253 if (mandated) n++; 254 if (n == 0) { 255 return Set.of(); 256 } else { 257 ModuleDescriptor.Modifier[] mods = new ModuleDescriptor.Modifier[n]; 258 if (open) mods[--n] = ModuleDescriptor.Modifier.OPEN; 259 if (synthetic) mods[--n] = ModuleDescriptor.Modifier.SYNTHETIC; 260 if (mandated) mods[--n] = ModuleDescriptor.Modifier.MANDATED; 261 return Set.of(mods); 262 } 263 } 264 265 /** 266 * Builds a {@code ModuleDescriptor} from the components. 267 */ 268 public ModuleDescriptor build(int hashCode) { 269 assert name != null; 270 return JLMA.newModuleDescriptor(name, 271 version, 272 modifiers(), 273 requires, 274 exports, 275 opens, 276 uses, 277 provides, 278 packages, 279 mainClass, 280 hashCode); 281 } 282 }