Package.java revision 16177:89ef4b822745
1178786Skmacy/* 2178786Skmacy * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. 3178786Skmacy * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4178786Skmacy * 5178786Skmacy * This code is free software; you can redistribute it and/or modify it 6178786Skmacy * under the terms of the GNU General Public License version 2 only, as 7178786Skmacy * published by the Free Software Foundation. Oracle designates this 8178786Skmacy * particular file as subject to the "Classpath" exception as provided 9178786Skmacy * by Oracle in the LICENSE file that accompanied this code. 10178786Skmacy * 11178786Skmacy * This code is distributed in the hope that it will be useful, but WITHOUT 12178786Skmacy * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13178786Skmacy * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14178786Skmacy * version 2 for more details (a copy is included in the LICENSE file that 15178786Skmacy * accompanied this code). 16178786Skmacy * 17178786Skmacy * You should have received a copy of the GNU General Public License version 18178786Skmacy * 2 along with this work; if not, write to the Free Software Foundation, 19178786Skmacy * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20178786Skmacy * 21178786Skmacy * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22178786Skmacy * or visit www.oracle.com if you need additional information or have any 23178786Skmacy * questions. 24178786Skmacy */ 25178786Skmacy 26178786Skmacypackage java.lang; 27178786Skmacy 28178786Skmacyimport java.lang.annotation.Annotation; 29178786Skmacyimport java.lang.reflect.AnnotatedElement; 30178786Skmacyimport java.lang.reflect.Module; 31178786Skmacyimport java.net.MalformedURLException; 32178786Skmacyimport java.net.URI; 33178786Skmacyimport java.net.URL; 34178786Skmacyimport java.security.AccessController; 35237263Snpimport java.security.PrivilegedAction; 36237263Snpimport java.util.Objects; 37237263Snp 38178786Skmacyimport jdk.internal.loader.BootLoader; 39178786Skmacyimport jdk.internal.reflect.CallerSensitive; 40178786Skmacyimport jdk.internal.reflect.Reflection; 41178786Skmacy 42178786Skmacy 43178786Skmacy/** 44178786Skmacy * Represents metadata about a run-time package associated with a class loader. 45178786Skmacy * Metadata includes annotations, versioning, and sealing. 46178786Skmacy * <p> 47178786Skmacy * Annotations for the run-time package are read from {@code package-info.class} 48178786Skmacy * at the same code source as classes in the run-time package. 49178786Skmacy * <p> 50178786Skmacy * The set of classes that make up the run-time package may implement a 51178786Skmacy * particular specification. The specification title, version, and vendor 52178786Skmacy * (indicating the owner/maintainer of the specification) can be provided 53178786Skmacy * when the {@code Package} is defined. An application can ask if the 54178786Skmacy * {@code Package} is compatible with a particular specification version 55178786Skmacy * by using the {@link #isCompatibleWith Package.isCompatibleWith(String)} 56178786Skmacy * method. In addition, information about the actual classes that make up the 57178786Skmacy * run-time package can be provided when the Package is defined. 58178786Skmacy * This information consists of an implementation title, version, and vendor 59178786Skmacy * (indicating the supplier of the classes). 60178786Skmacy * <p> 61178786Skmacy * A {@code Package} may be explicitly defined with 62178786Skmacy * the {@link ClassLoader#definePackage(String, String, String, String, 63178786Skmacy * String, String, String, URL)} method. 64178786Skmacy * The caller supplies the specification and implementation titles, versions, and 65178786Skmacy * vendors. The caller also indicates whether the package is 66178786Skmacy * {@linkplain java.util.jar.Attributes.Name#SEALED sealed}. 67178786Skmacy * If a {@code Package} is not explicitly defined for a run-time package when 68178786Skmacy * a class in that run-time package is defined, then a {@code Package} is 69178786Skmacy * automatically defined by the class's defining class loader, as follows. 70178786Skmacy * <p> 71178786Skmacy * A {@code Package} automatically defined for classes in a named module has 72178786Skmacy * the following properties: 73178786Skmacy * <ul> 74178786Skmacy * <li>The name of the package is derived from the {@linkplain Class#getName() binary names} 75178786Skmacy * of the classes. Since classes in a named module must be in a named package, 76178786Skmacy * the derived name is never empty.</li> 77178786Skmacy * <li>The package is sealed with the {@linkplain java.lang.module.ModuleReference#location() 78178786Skmacy * module location} as the code source, if known.</li> 79178786Skmacy * <li>The specification and implementation titles, versions, and vendors 80178786Skmacy * are unspecified.</li> 81178786Skmacy * <li>Any annotations on the package are read from {@code package-info.class} 82178786Skmacy * as specified above.</li> 83178786Skmacy * </ul> 84178786Skmacy * <p> 85178786Skmacy * A {@code Package} automatically defined for classes in an unnamed module 86178786Skmacy * has the following properties: 87178786Skmacy * <ul> 88178786Skmacy * <li>The name of the package is either {@code ""} (for classes in an unnamed package) 89178786Skmacy * or derived from the {@linkplain Class#getName() binary names} of the classes 90178786Skmacy * (for classes in a named package).</li> 91178786Skmacy * <li>The package is not sealed.</li> 92178786Skmacy * <li>The specification and implementation titles, versions, and vendors 93178786Skmacy * are unspecified.</li> 94178786Skmacy * <li>Any annotations on the package are read from {@code package-info.class} 95178786Skmacy * as specified above.</li> 96178786Skmacy * </ul> 97178786Skmacy * 98178786Skmacy * <p> 99178786Skmacy * A {@code Package} can be obtained with the {@link Package#getPackage 100178786Skmacy * Package.getPackage(String)} and {@link ClassLoader#getDefinedPackage 101178786Skmacy * ClassLoader.getDefinedPackage(String)} methods. 102178786Skmacy * Every {@code Package} defined by a class loader can be obtained 103178786Skmacy * with the {@link Package#getPackages Package.getPackages()} and 104178786Skmacy * {@link ClassLoader#getDefinedPackages} methods. 105178786Skmacy * 106178786Skmacy * @jvms 5.3 Run-time package 107178786Skmacy * @see <a href="../../../technotes/guides/jar/jar.html#versioning"> 108178786Skmacy * The JAR File Specification: Package Versioning</a> 109178786Skmacy * @see <a href="../../../technotes/guides/jar/jar.html#sealing"> 110178786Skmacy * The JAR File Specification: Package Sealing</a> 111178786Skmacy * @see ClassLoader#definePackage(String, String, String, String, String, String, String, URL) 112178786Skmacy * 113178786Skmacy * @since 1.2 114178786Skmacy */ 115178786Skmacypublic class Package extends NamedPackage implements java.lang.reflect.AnnotatedElement { 116178786Skmacy /** 117178786Skmacy * Return the name of this package. 118178786Skmacy * 119178786Skmacy * @return The fully-qualified name of this package as defined in section 6.5.3 of 120178786Skmacy * <cite>The Java™ Language Specification</cite>, 121178786Skmacy * for example, {@code java.lang} 122178786Skmacy */ 123178786Skmacy public String getName() { 124178786Skmacy return packageName(); 125178786Skmacy } 126178786Skmacy 127178786Skmacy /** 128178786Skmacy * Return the title of the specification that this package implements. 129178786Skmacy * @return the specification title, {@code null} is returned if it is not known. 130178786Skmacy */ 131178786Skmacy public String getSpecificationTitle() { 132178786Skmacy return versionInfo.specTitle; 133178786Skmacy } 134178786Skmacy 135178786Skmacy /** 136178786Skmacy * Returns the version number of the specification 137178786Skmacy * that this package implements. 138178786Skmacy * This version string must be a sequence of non-negative decimal 139178786Skmacy * integers separated by "."'s and may have leading zeros. 140178786Skmacy * When version strings are compared the most significant 141178786Skmacy * numbers are compared. 142178786Skmacy * 143178786Skmacy * 144178786Skmacy * <p>Specification version numbers use a syntax that consists of non-negative 145178786Skmacy * decimal integers separated by periods ".", for example "2.0" or 146178786Skmacy * "1.2.3.4.5.6.7". This allows an extensible number to be used to represent 147178786Skmacy * major, minor, micro, etc. versions. The version specification is described 148178786Skmacy * by the following formal grammar: 149178786Skmacy * <blockquote> 150178786Skmacy * <dl> 151178786Skmacy * <dt><i>SpecificationVersion:</i> 152178786Skmacy * <dd><i>Digits RefinedVersion<sub>opt</sub></i> 153178786Skmacy 154178786Skmacy * <dt><i>RefinedVersion:</i> 155178786Skmacy * <dd>{@code .} <i>Digits</i> 156178786Skmacy * <dd>{@code .} <i>Digits RefinedVersion</i> 157178786Skmacy * 158178786Skmacy * <dt><i>Digits:</i> 159178786Skmacy * <dd><i>Digit</i> 160178786Skmacy * <dd><i>Digits</i> 161178786Skmacy * 162178786Skmacy * <dt><i>Digit:</i> 163178786Skmacy * <dd>any character for which {@link Character#isDigit} returns {@code true}, 164178786Skmacy * e.g. 0, 1, 2, ... 165178786Skmacy * </dl> 166178786Skmacy * </blockquote> 167178786Skmacy * 168178786Skmacy * @return the specification version, {@code null} is returned if it is not known. 169178786Skmacy */ 170178786Skmacy public String getSpecificationVersion() { 171178786Skmacy return versionInfo.specVersion; 172178786Skmacy } 173178786Skmacy 174178786Skmacy /** 175178786Skmacy * Return the name of the organization, vendor, 176178786Skmacy * or company that owns and maintains the specification 177178786Skmacy * of the classes that implement this package. 178178786Skmacy * @return the specification vendor, {@code null} is returned if it is not known. 179178786Skmacy */ 180178786Skmacy public String getSpecificationVendor() { 181178786Skmacy return versionInfo.specVendor; 182178786Skmacy } 183178786Skmacy 184178786Skmacy /** 185178786Skmacy * Return the title of this package. 186178786Skmacy * @return the title of the implementation, {@code null} is returned if it is not known. 187178786Skmacy */ 188178786Skmacy public String getImplementationTitle() { 189178786Skmacy return versionInfo.implTitle; 190178786Skmacy } 191178786Skmacy 192178786Skmacy /** 193178786Skmacy * Return the version of this implementation. It consists of any string 194178786Skmacy * assigned by the vendor of this implementation and does 195178786Skmacy * not have any particular syntax specified or expected by the Java 196178786Skmacy * runtime. It may be compared for equality with other 197178786Skmacy * package version strings used for this implementation 198178786Skmacy * by this vendor for this package. 199178786Skmacy * @return the version of the implementation, {@code null} is returned if it is not known. 200178786Skmacy */ 201178786Skmacy public String getImplementationVersion() { 202178786Skmacy return versionInfo.implVersion; 203178786Skmacy } 204178786Skmacy 205178786Skmacy /** 206178786Skmacy * Returns the vendor that implemented this package, {@code null} 207178786Skmacy * is returned if it is not known. 208178786Skmacy * @return the vendor that implemented this package, {@code null} 209178786Skmacy * is returned if it is not known. 210178786Skmacy */ 211178786Skmacy public String getImplementationVendor() { 212178786Skmacy return versionInfo.implVendor; 213178786Skmacy } 214178786Skmacy 215178786Skmacy /** 216178786Skmacy * Returns true if this package is sealed. 217178786Skmacy * 218178786Skmacy * @return true if the package is sealed, false otherwise 219178786Skmacy */ 220178786Skmacy public boolean isSealed() { 221178786Skmacy return module().isNamed() || versionInfo.sealBase != null; 222178786Skmacy } 223178786Skmacy 224178786Skmacy /** 225178786Skmacy * Returns true if this package is sealed with respect to the specified 226178786Skmacy * code source {@code url}. 227178786Skmacy * 228178786Skmacy * @param url the code source URL 229178786Skmacy * @return true if this package is sealed with respect to the given {@code url} 230178786Skmacy */ 231178786Skmacy public boolean isSealed(URL url) { 232178786Skmacy Objects.requireNonNull(url); 233178786Skmacy 234178786Skmacy URL sealBase = null; 235178786Skmacy if (versionInfo != VersionInfo.NULL_VERSION_INFO) { 236178786Skmacy sealBase = versionInfo.sealBase; 237178786Skmacy } else { 238178786Skmacy try { 239178786Skmacy URI uri = location(); 240178786Skmacy sealBase = uri != null ? uri.toURL() : null; 241178786Skmacy } catch (MalformedURLException e) { 242178786Skmacy } 243178786Skmacy } 244178786Skmacy return url.equals(sealBase); 245178786Skmacy } 246178786Skmacy 247178786Skmacy /** 248178786Skmacy * Compare this package's specification version with a 249178786Skmacy * desired version. It returns true if 250178786Skmacy * this packages specification version number is greater than or equal 251178786Skmacy * to the desired version number. <p> 252178786Skmacy * 253178786Skmacy * Version numbers are compared by sequentially comparing corresponding 254178786Skmacy * components of the desired and specification strings. 255178786Skmacy * Each component is converted as a decimal integer and the values 256178786Skmacy * compared. 257178786Skmacy * If the specification value is greater than the desired 258178786Skmacy * value true is returned. If the value is less false is returned. 259178786Skmacy * If the values are equal the period is skipped and the next pair of 260178786Skmacy * components is compared. 261178786Skmacy * 262178786Skmacy * @param desired the version string of the desired version. 263178786Skmacy * @return true if this package's version number is greater 264178786Skmacy * than or equal to the desired version number 265178786Skmacy * 266178786Skmacy * @exception NumberFormatException if the current version is not known or 267178786Skmacy * the desired or current version is not of the correct dotted form. 268178786Skmacy */ 269178786Skmacy public boolean isCompatibleWith(String desired) 270178786Skmacy throws NumberFormatException 271178786Skmacy { 272178786Skmacy if (versionInfo.specVersion == null || versionInfo.specVersion.length() < 1) { 273178786Skmacy throw new NumberFormatException("Empty version string"); 274178786Skmacy } 275178786Skmacy 276178786Skmacy String [] sa = versionInfo.specVersion.split("\\.", -1); 277178786Skmacy int [] si = new int[sa.length]; 278237263Snp for (int i = 0; i < sa.length; i++) { 279237263Snp si[i] = Integer.parseInt(sa[i]); 280237263Snp if (si[i] < 0) 281237263Snp throw NumberFormatException.forInputString("" + si[i]); 282237263Snp } 283237263Snp 284237263Snp String [] da = desired.split("\\.", -1); 285237263Snp int [] di = new int[da.length]; 286237263Snp for (int i = 0; i < da.length; i++) { 287237263Snp di[i] = Integer.parseInt(da[i]); 288237263Snp if (di[i] < 0) 289237263Snp throw NumberFormatException.forInputString("" + di[i]); 290237263Snp } 291237263Snp 292237263Snp int len = Math.max(di.length, si.length); 293237263Snp for (int i = 0; i < len; i++) { 294178786Skmacy int d = (i < di.length ? di[i] : 0); 295178786Skmacy int s = (i < si.length ? si[i] : 0); 296178786Skmacy if (s < d) 297178786Skmacy return false; 298178786Skmacy if (s > d) 299178786Skmacy return true; 300178786Skmacy } 301178786Skmacy return true; 302178786Skmacy } 303178786Skmacy 304178786Skmacy /** 305178786Skmacy * Finds a package by name in the caller's class loader and its 306178786Skmacy * ancestors. 307178786Skmacy * <p> 308178786Skmacy * If the caller's class loader defines a {@code Package} of the given name, 309237263Snp * the {@code Package} is returned. Otherwise, the ancestors of the 310237263Snp * caller's class loader are searched recursively (parent by parent) 311237263Snp * for a {@code Package} of the given name. 312178786Skmacy * <p> 313237263Snp * Calling this method is equivalent to calling {@link ClassLoader#getPackage} 314178786Skmacy * on a {@code ClassLoader} instance which is the caller's class loader. 315178786Skmacy * 316178786Skmacy * @param name A package name, such as "{@code java.lang}". 317178786Skmacy * @return The {@code Package} of the given name defined by the caller's 318178786Skmacy * class loader or its ancestors, or {@code null} if not found. 319178786Skmacy * 320178786Skmacy * @throws NullPointerException 321178786Skmacy * if {@code name} is {@code null}. 322178786Skmacy * 323178786Skmacy * @deprecated 324178786Skmacy * If multiple class loaders delegate to each other and define classes 325178786Skmacy * with the same package name, and one such loader relies on the lookup 326178786Skmacy * behavior of {@code getPackage} to return a {@code Package} from 327178786Skmacy * a parent loader, then the properties exposed by the {@code Package} 328237263Snp * may not be as expected in the rest of the program. 329237263Snp * For example, the {@code Package} will only expose annotations from the 330178786Skmacy * {@code package-info.class} file defined by the parent loader, even if 331178786Skmacy * annotations exist in a {@code package-info.class} file defined by 332178786Skmacy * a child loader. A more robust approach is to use the 333178786Skmacy * {@link ClassLoader#getDefinedPackage} method which returns 334237263Snp * a {@code Package} for the specified class loader. 335178786Skmacy * 336178786Skmacy * @see ClassLoader#getDefinedPackage 337178786Skmacy */ 338178786Skmacy @CallerSensitive 339178786Skmacy @Deprecated(since="9") 340178786Skmacy @SuppressWarnings("deprecation") 341178786Skmacy public static Package getPackage(String name) { 342178786Skmacy ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass()); 343237263Snp return l != null ? l.getPackage(name) : BootLoader.getDefinedPackage(name); 344237263Snp } 345178786Skmacy 346178786Skmacy /** 347178786Skmacy * Returns all of the {@code Package}s defined by the caller's class loader 348178786Skmacy * and its ancestors. The returned array may contain more than one 349178786Skmacy * {@code Package} object of the same package name, each defined by 350178786Skmacy * a different class loader in the class loader hierarchy. 351178786Skmacy * <p> 352178786Skmacy * Calling this method is equivalent to calling {@link ClassLoader#getPackages} 353178786Skmacy * on a {@code ClassLoader} instance which is the caller's class loader. 354178786Skmacy * 355178786Skmacy * @return The array of {@code Package} objects defined by this 356178786Skmacy * class loader and its ancestors 357178786Skmacy * 358178786Skmacy * @see ClassLoader#getDefinedPackages 359178786Skmacy */ 360178786Skmacy @CallerSensitive 361178786Skmacy public static Package[] getPackages() { 362178786Skmacy ClassLoader cl = ClassLoader.getClassLoader(Reflection.getCallerClass()); 363178786Skmacy return cl != null ? cl.getPackages() : BootLoader.packages().toArray(Package[]::new); 364178786Skmacy } 365178786Skmacy 366178786Skmacy /** 367178786Skmacy * Return the hash code computed from the package name. 368178786Skmacy * @return the hash code computed from the package name. 369178786Skmacy */ 370178786Skmacy @Override 371178786Skmacy public int hashCode(){ 372178786Skmacy return packageName().hashCode(); 373178786Skmacy } 374178786Skmacy 375178786Skmacy /** 376178786Skmacy * Returns the string representation of this Package. 377178786Skmacy * Its value is the string "package " and the package name. 378178786Skmacy * If the package title is defined it is appended. 379178786Skmacy * If the package version is defined it is appended. 380178786Skmacy * @return the string representation of the package. 381178786Skmacy */ 382178786Skmacy @Override 383178786Skmacy public String toString() { 384178786Skmacy String spec = versionInfo.specTitle; 385178786Skmacy String ver = versionInfo.specVersion; 386178786Skmacy if (spec != null && spec.length() > 0) 387178786Skmacy spec = ", " + spec; 388178786Skmacy else 389178786Skmacy spec = ""; 390178786Skmacy if (ver != null && ver.length() > 0) 391178786Skmacy ver = ", version " + ver; 392178786Skmacy else 393178786Skmacy ver = ""; 394178786Skmacy return "package " + packageName() + spec + ver; 395178786Skmacy } 396178786Skmacy 397178786Skmacy private Class<?> getPackageInfo() { 398178786Skmacy if (packageInfo == null) { 399178786Skmacy // find package-info.class defined by loader 400178786Skmacy String cn = packageName() + ".package-info"; 401178786Skmacy Module module = module(); 402178786Skmacy PrivilegedAction<ClassLoader> pa = module::getClassLoader; 403178786Skmacy ClassLoader loader = AccessController.doPrivileged(pa); 404178786Skmacy Class<?> c; 405178786Skmacy if (loader != null) { 406178786Skmacy c = loader.loadClass(module, cn); 407178786Skmacy } else { 408178786Skmacy c = BootLoader.loadClass(module, cn); 409178786Skmacy } 410178786Skmacy 411178786Skmacy if (c != null) { 412178786Skmacy packageInfo = c; 413178786Skmacy } else { 414178786Skmacy // store a proxy for the package info that has no annotations 415178786Skmacy class PackageInfoProxy {} 416178786Skmacy packageInfo = PackageInfoProxy.class; 417178786Skmacy } 418178786Skmacy } 419178786Skmacy return packageInfo; 420178786Skmacy } 421178786Skmacy 422178786Skmacy /** 423178786Skmacy * @throws NullPointerException {@inheritDoc} 424178786Skmacy * @since 1.5 425178786Skmacy */ 426178786Skmacy public <A extends Annotation> A getAnnotation(Class<A> annotationClass) { 427178786Skmacy return getPackageInfo().getAnnotation(annotationClass); 428178786Skmacy } 429178786Skmacy 430178786Skmacy /** 431178786Skmacy * {@inheritDoc} 432178786Skmacy * @throws NullPointerException {@inheritDoc} 433178786Skmacy * @since 1.5 434178786Skmacy */ 435178786Skmacy @Override 436178786Skmacy public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { 437178786Skmacy return AnnotatedElement.super.isAnnotationPresent(annotationClass); 438178786Skmacy } 439178786Skmacy 440178786Skmacy /** 441178786Skmacy * @throws NullPointerException {@inheritDoc} 442178786Skmacy * @since 1.8 443178786Skmacy */ 444178786Skmacy @Override 445178786Skmacy public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass) { 446178786Skmacy return getPackageInfo().getAnnotationsByType(annotationClass); 447178786Skmacy } 448178786Skmacy 449178786Skmacy /** 450178786Skmacy * @since 1.5 451178786Skmacy */ 452178786Skmacy public Annotation[] getAnnotations() { 453178786Skmacy return getPackageInfo().getAnnotations(); 454178786Skmacy } 455178786Skmacy 456178786Skmacy /** 457178786Skmacy * @throws NullPointerException {@inheritDoc} 458178786Skmacy * @since 1.8 459178786Skmacy */ 460178786Skmacy @Override 461178786Skmacy public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) { 462178786Skmacy return getPackageInfo().getDeclaredAnnotation(annotationClass); 463178786Skmacy } 464178786Skmacy 465178786Skmacy /** 466178786Skmacy * @throws NullPointerException {@inheritDoc} 467178786Skmacy * @since 1.8 468178786Skmacy */ 469178786Skmacy @Override 470178786Skmacy public <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A> annotationClass) { 471178786Skmacy return getPackageInfo().getDeclaredAnnotationsByType(annotationClass); 472178786Skmacy } 473178786Skmacy 474178786Skmacy /** 475178786Skmacy * @since 1.5 476178786Skmacy */ 477178786Skmacy public Annotation[] getDeclaredAnnotations() { 478178786Skmacy return getPackageInfo().getDeclaredAnnotations(); 479178786Skmacy } 480178786Skmacy 481178786Skmacy /** 482178786Skmacy * Construct a package instance for an unnamed module 483178786Skmacy * with the specified version information. 484178786Skmacy * 485178786Skmacy * @apiNote 486178786Skmacy * This method should not be called to define a Package for named module. 487178786Skmacy * 488178786Skmacy * @param name the name of the package 489178786Skmacy * @param spectitle the title of the specification 490178786Skmacy * @param specversion the version of the specification 491178786Skmacy * @param specvendor the organization that maintains the specification 492178786Skmacy * @param impltitle the title of the implementation 493178786Skmacy * @param implversion the version of the implementation 494178786Skmacy * @param implvendor the organization that maintains the implementation 495178786Skmacy * @param sealbase code source where this Package comes from 496178786Skmacy * @param loader defining class loader 497178786Skmacy */ 498178786Skmacy Package(String name, 499178786Skmacy String spectitle, String specversion, String specvendor, 500178786Skmacy String impltitle, String implversion, String implvendor, 501178786Skmacy URL sealbase, ClassLoader loader) 502178786Skmacy { 503178786Skmacy super(Objects.requireNonNull(name), 504178786Skmacy loader != null ? loader.getUnnamedModule() 505178786Skmacy : BootLoader.getUnnamedModule()); 506178786Skmacy 507178786Skmacy this.versionInfo = VersionInfo.getInstance(spectitle, specversion, 508178786Skmacy specvendor, impltitle, 509178786Skmacy implversion, implvendor, 510178786Skmacy sealbase); 511178786Skmacy } 512178786Skmacy 513178786Skmacy Package(String name, Module module) { 514178786Skmacy super(name, module); 515178786Skmacy this.versionInfo = VersionInfo.NULL_VERSION_INFO; 516178786Skmacy } 517178786Skmacy 518178786Skmacy /* 519178786Skmacy * Versioning information. Only for packages in unnamed modules. 520178786Skmacy */ 521178786Skmacy static class VersionInfo { 522178786Skmacy static final VersionInfo NULL_VERSION_INFO 523178786Skmacy = new VersionInfo(null, null, null, null, null, null, null); 524178786Skmacy 525178786Skmacy private final String specTitle; 526178786Skmacy private final String specVersion; 527178786Skmacy private final String specVendor; 528178786Skmacy private final String implTitle; 529178786Skmacy private final String implVersion; 530178786Skmacy private final String implVendor; 531178786Skmacy private final URL sealBase; 532178786Skmacy 533178786Skmacy static VersionInfo getInstance(String spectitle, String specversion, 534178786Skmacy String specvendor, String impltitle, 535178786Skmacy String implversion, String implvendor, 536178786Skmacy URL sealbase) { 537178786Skmacy if (spectitle == null && specversion == null && 538178786Skmacy specvendor == null && impltitle == null && 539178786Skmacy implvendor == null && sealbase == null) { 540178786Skmacy return NULL_VERSION_INFO; 541178786Skmacy } 542178786Skmacy return new VersionInfo(spectitle, specversion, specvendor, 543178786Skmacy impltitle, implversion, implvendor, 544178786Skmacy sealbase); 545178786Skmacy } 546178786Skmacy 547178786Skmacy private VersionInfo(String spectitle, String specversion, 548178786Skmacy String specvendor, String impltitle, 549178786Skmacy String implversion, String implvendor, 550178786Skmacy URL sealbase) 551178786Skmacy { 552178786Skmacy this.implTitle = impltitle; 553178786Skmacy this.implVersion = implversion; 554178786Skmacy this.implVendor = implvendor; 555178786Skmacy this.specTitle = spectitle; 556178786Skmacy this.specVersion = specversion; 557237263Snp this.specVendor = specvendor; 558237263Snp this.sealBase = sealbase; 559237263Snp } 560237263Snp } 561237263Snp 562237263Snp private final VersionInfo versionInfo; 563178786Skmacy private Class<?> packageInfo; 564178786Skmacy} 565178786Skmacy