1 /* 2 * Copyright (c) 2014, 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 26 package java.lang.module; 27 28 import java.io.IOException; 29 import java.io.UncheckedIOException; 30 import java.net.URI; 31 import java.util.Objects; 32 import java.util.Optional; 33 import java.util.function.Supplier; 34 35 import jdk.internal.module.ModuleHashes.HashSupplier; 36 37 38 /** 39 * A reference to a module's content. 40 * 41 * <p> A module reference contains the module's descriptor and its location, if 42 * known. It also has the ability to create a {@link ModuleReader} in order to 43 * access the module's content, which may be inside the Java run-time system 44 * itself or in an artifact such as a modular JAR file. 45 * 46 * @see ModuleFinder 47 * @see ModuleReader 48 * @since 9 49 */ 50 51 public final class ModuleReference { 52 53 private final ModuleDescriptor descriptor; 54 private final URI location; 55 private final Supplier<ModuleReader> readerSupplier; 56 57 // true if this is a reference to a patched module 58 private boolean patched; 59 60 // the function that computes the hash of this module reference 61 private final HashSupplier hasher; 62 63 // cached hash string to avoid needing to compute it many times 64 private String cachedHash; 65 66 67 /** 68 * Constructs a new instance of this class. 69 */ 70 ModuleReference(ModuleDescriptor descriptor, 71 URI location, 72 Supplier<ModuleReader> readerSupplier, 73 boolean patched, 74 HashSupplier hasher) 75 76 { 77 this.descriptor = Objects.requireNonNull(descriptor); 78 this.location = location; 79 this.readerSupplier = Objects.requireNonNull(readerSupplier); 80 this.patched = patched; 81 this.hasher = hasher; 82 } 83 84 /** 85 * Constructs a new instance of this class. 86 */ 87 ModuleReference(ModuleDescriptor descriptor, 88 URI location, 89 Supplier<ModuleReader> readerSupplier, 90 HashSupplier hasher) 91 92 { 93 this(descriptor, location, readerSupplier, false, hasher); 94 } 95 96 97 /** 98 * Constructs a new instance of this class. 99 * 100 * <p> The {@code readSupplier} parameter is the supplier of the {@link 101 * ModuleReader} that may be used to read the module content. Its {@link 102 * Supplier#get() get()} method throws {@link UncheckedIOException} if an 103 * I/O error occurs opening the module content. The {@code get()} method 104 * throws {@link SecurityException} if opening the module is denied by the 105 * security manager. 106 * 107 * @param descriptor 108 * The module descriptor 109 * @param location 110 * The module location or {@code null} if not known 111 * @param readerSupplier 112 * The {@code Supplier} of the {@code ModuleReader} 113 */ 114 public ModuleReference(ModuleDescriptor descriptor, 115 URI location, 116 Supplier<ModuleReader> readerSupplier) 117 { 118 this(descriptor, location, readerSupplier, false, null); 119 } 120 121 /** 122 * Returns the module descriptor. 123 * 124 * @return The module descriptor 125 */ 126 public ModuleDescriptor descriptor() { 127 return descriptor; 128 } 129 130 131 /** 132 * Returns the location of this module's content, if known. 133 * 134 * <p> This URI, when present, is used as the {@linkplain 135 * java.security.CodeSource#getLocation location} value of a {@link 136 * java.security.CodeSource CodeSource} so that a module's classes can be 137 * granted specific permissions when loaded by a {@link 138 * java.security.SecureClassLoader SecureClassLoader}. 139 * 140 * @return The location or an empty {@code Optional} if not known 141 */ 142 public Optional<URI> location() { 143 return Optional.ofNullable(location); 144 } 145 146 147 /** 148 * Opens the module content for reading. 149 * 150 * <p> This method opens the module content by invoking the {@link 151 * Supplier#get() get()} method of the {@code readSupplier} specified at 152 * construction time. </p> 153 * 154 * @return A {@code ModuleReader} to read the module 155 * 156 * @throws IOException 157 * If an I/O error occurs 158 * @throws SecurityException 159 * If denied by the security manager 160 */ 161 public ModuleReader open() throws IOException { 162 try { 163 return readerSupplier.get(); 164 } catch (UncheckedIOException e) { 165 throw e.getCause(); 166 } 167 168 } 169 170 171 /** 172 * Returns {@code true} if this module has been patched via --patch-module. 173 */ 174 boolean isPatched() { 175 return patched; 176 } 177 178 /** 179 * Returns the hash supplier for this module. 180 */ 181 HashSupplier hasher() { 182 return hasher; 183 } 184 185 /** 186 * Computes the hash of this module, returning it as a hex string. 187 * Returns {@code null} if the hash cannot be computed. 188 * 189 * @throws java.io.UncheckedIOException if an I/O error occurs 190 */ 191 String computeHash(String algorithm) { 192 String result = cachedHash; 193 if (result != null) 194 return result; 195 if (hasher == null) 196 return null; 197 cachedHash = result = hasher.generate(algorithm); 198 return result; 199 } 200 201 /** 202 * Computes a hash code for this module reference. 203 * 204 * <p> The hash code is based upon the components of the reference, and 205 * satisfies the general contract of the {@link Object#hashCode 206 * Object.hashCode} method. </p> 207 * 208 * @return The hash-code value for this module reference 209 */ 210 @Override 211 public int hashCode() { 212 int hc = hash; 213 if (hc == 0) { 214 hc = Objects.hash(descriptor, location, readerSupplier, hasher, 215 Boolean.valueOf(patched)); 216 if (hc == 0) 217 hc = -1; 218 hash = hc; 219 } 220 return hc; 221 } 222 223 private int hash; 224 225 /** 226 * Tests this module reference for equality with the given object. 227 * 228 * <p> If the given object is not a {@code ModuleReference} then this 229 * method returns {@code false}. Two module references are equal if their 230 * module descriptors are equal, their locations are equal or both unknown, 231 * and were created with equal supplier objects to access the module 232 * content. </p> 233 * 234 * <p> This method satisfies the general contract of the {@link 235 * java.lang.Object#equals(Object) Object.equals} method. </p> 236 * 237 * @param ob 238 * the object to which this object is to be compared 239 * 240 * @return {@code true} if, and only if, the given object is a module 241 * reference that is equal to this module reference 242 */ 243 @Override 244 public boolean equals(Object ob) { 245 if (!(ob instanceof ModuleReference)) 246 return false; 247 ModuleReference that = (ModuleReference)ob; 248 249 return Objects.equals(this.descriptor, that.descriptor) 250 && Objects.equals(this.location, that.location) 251 && Objects.equals(this.readerSupplier, that.readerSupplier) 252 && Objects.equals(this.hasher, that.hasher) 253 && this.patched == that.patched; 254 } 255 256 /** 257 * Returns a string describing this module reference. 258 * 259 * @return A string describing this module reference 260 */ 261 @Override 262 public String toString() { 263 return ("[module " + descriptor().name() 264 + ", location=" + location + "]"); 265 } 266 267 }