jdk/src/java.base/share/classes/java/lang/Package.java
changeset 36511 9d0388c6b336
parent 32649 2ee9017c7597
child 37363 329dba26ffd2
equal deleted inserted replaced
36510:043f1af70518 36511:9d0388c6b336
     1 /*
     1 /*
     2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package java.lang;
    26 package java.lang;
    27 
    27 
       
    28 import java.lang.annotation.Annotation;
    28 import java.lang.reflect.AnnotatedElement;
    29 import java.lang.reflect.AnnotatedElement;
    29 
    30 import java.lang.reflect.Module;
    30 import java.io.File;
    31 import java.net.MalformedURLException;
    31 import java.io.FileInputStream;
    32 import java.net.URI;
    32 import java.io.IOException;
       
    33 import java.net.URL;
    33 import java.net.URL;
    34 import java.net.MalformedURLException;
       
    35 import java.security.AccessController;
    34 import java.security.AccessController;
    36 import java.security.PrivilegedAction;
    35 import java.security.PrivilegedAction;
    37 
    36 import java.util.Objects;
    38 import java.util.concurrent.ConcurrentHashMap;
    37 
    39 import java.util.jar.JarInputStream;
    38 import jdk.internal.loader.BootLoader;
    40 import java.util.jar.Manifest;
       
    41 import java.util.jar.Attributes;
       
    42 import java.util.jar.Attributes.Name;
       
    43 import java.util.Map;
       
    44 
       
    45 import sun.net.www.ParseUtil;
       
    46 import sun.reflect.CallerSensitive;
    39 import sun.reflect.CallerSensitive;
    47 import sun.reflect.Reflection;
    40 import sun.reflect.Reflection;
    48 
    41 
    49 import java.lang.annotation.Annotation;
       
    50 
    42 
    51 /**
    43 /**
    52  * {@code Package} objects contain version information
    44  * Represents metadata about a run-time package associated with a class loader.
    53  * about the implementation and specification of a Java package.
    45  * Metadata includes annotations, versioning, and sealing.
    54  * This versioning information is retrieved and made available
    46  * <p>
    55  * by the {@link ClassLoader} instance that
    47  * Annotations for the run-time package are read from {@code package-info.class}
    56  * loaded the class(es).  Typically, it is stored in the manifest that is
    48  * at the same code source as classes in the run-time package.
    57  * distributed with the classes.
    49  * <p>
    58  *
    50  * The set of classes that make up the run-time package may implement a
    59  * <p>The set of classes that make up the package may implement a
    51  * particular specification. The specification title, version, and vendor
    60  * particular specification and if so the specification title, version number,
    52  * (indicating the owner/maintainer of the specification) can be provided
    61  * and vendor strings identify that specification.
    53  * when the {@code Package} is defined. An application can ask if the
    62  * An application can ask if the package is
    54  * {@code Package} is compatible with a particular specification version
    63  * compatible with a particular version, see the {@link
    55  * by using the {@link #isCompatibleWith Package.isCompatibleWith(String)}
    64  * #isCompatibleWith isCompatibleWith}
    56  * method. In addition, information about the actual classes that make up the
    65  * method for details.
    57  * run-time package can be provided when the Package is defined.
    66  *
    58  * This information consists of an implementation title, version, and vendor
    67  * <p>Specification version numbers use a syntax that consists of nonnegative
    59  * (indicating the supplier of the classes).
    68  * decimal integers separated by periods ".", for example "2.0" or
    60  * <p>
    69  * "1.2.3.4.5.6.7".  This allows an extensible number to be used to represent
    61  * A {@code Package} may be explicitly defined with
    70  * major, minor, micro, etc. versions.  The version specification is described
    62  * the {@link ClassLoader#definePackage(String, String, String, String,
    71  * by the following formal grammar:
    63  * String, String, String, URL)} method.
    72  * <blockquote>
    64  * The caller supplies the specification and implementation titles, versions, and
    73  * <dl>
    65  * vendors. The caller also indicates whether the package is
    74  * <dt><i>SpecificationVersion:</i>
    66  * {@linkplain java.util.jar.Attributes.Name#SEALED sealed}.
    75  * <dd><i>Digits RefinedVersion<sub>opt</sub></i>
    67  * If a {@code Package} is not explicitly defined for a run-time package when
    76 
    68  * a class in that run-time package is defined, then a {@code Package} is
    77  * <dt><i>RefinedVersion:</i>
    69  * automatically defined by the class's defining class loader, as follows.
    78  * <dd>{@code .} <i>Digits</i>
    70  * <p>
    79  * <dd>{@code .} <i>Digits RefinedVersion</i>
    71  * A {@code Package} automatically defined for classes in a named module has
    80  *
    72  * the following properties:
    81  * <dt><i>Digits:</i>
    73  * <ul>
    82  * <dd><i>Digit</i>
    74  * <li>The name of the package is derived from the {@linkplain Class#getName() binary names}
    83  * <dd><i>Digits</i>
    75  *     of the classes. Since classes in a named module must be in a named package,
    84  *
    76  *     the derived name is never empty.</li>
    85  * <dt><i>Digit:</i>
    77  * <li>The package is sealed with the {@linkplain java.lang.module.ModuleReference#location()
    86  * <dd>any character for which {@link Character#isDigit} returns {@code true},
    78  *     module location} as the code source, if known.</li>
    87  * e.g. 0, 1, 2, ...
    79  * <li>The specification and implementation titles, versions, and vendors
    88  * </dl>
    80  *     are unspecified.</li>
    89  * </blockquote>
    81  * <li>Any annotations on the package are read from {@code package-info.class}
    90  *
    82  *     as specified above.</li>
    91  * <p>The implementation title, version, and vendor strings identify an
    83  * </ul>
    92  * implementation and are made available conveniently to enable accurate
    84  * <p>
    93  * reporting of the packages involved when a problem occurs. The contents
    85  * A {@code Package} automatically defined for classes in an unnamed module
    94  * all three implementation strings are vendor specific. The
    86  * has the following properties:
    95  * implementation version strings have no specified syntax and should
    87  * <ul>
    96  * only be compared for equality with desired version identifiers.
    88  * <li>The name of the package is either {@code ""} (for classes in an unnamed package)
    97  *
    89  *     or derived from the {@linkplain Class#getName() binary names} of the classes
    98  * <p>Within each {@code ClassLoader} instance all classes from the same
    90  *     (for classes in a named package).</li>
    99  * java package have the same Package object.  The static methods allow a package
    91  * <li>The package is not sealed.</li>
   100  * to be found by name or the set of all packages known to the current class
    92  * <li>The specification and implementation titles, versions, and vendors
   101  * loader to be found.
    93  *     are unspecified.</li>
   102  *
    94  * <li>Any annotations on the package are read from {@code package-info.class}
   103  * @see ClassLoader#definePackage
    95  *     as specified above.</li>
       
    96  * </ul>
       
    97  *
       
    98  * <p>
       
    99  * A {@code Package} can be obtained with the {@link Package#getPackage
       
   100  * Package.getPackage(String)} and {@link ClassLoader#getDefinedPackage
       
   101  * ClassLoader.getDefinedPackage(String)} methods.
       
   102  * Every {@code Package} defined by a class loader can be obtained
       
   103  * with the {@link Package#getPackages Package.getPackages()} and
       
   104  * {@link ClassLoader#getDefinedPackages} methods.
       
   105  *
       
   106  * @jvms 5.3 Run-time package
       
   107  * @see <a href="../../../technotes/guides/jar/jar.html#versioning">
       
   108  * The JAR File Specification: Package Versioning</a>
       
   109  * @see <a href="../../../technotes/guides/jar/jar.html#sealing">
       
   110  * The JAR File Specification: Package Sealing</a>
       
   111  * @see ClassLoader#definePackage(String, String, String, String, String, String, String, URL)
       
   112  *
   104  * @since 1.2
   113  * @since 1.2
   105  */
   114  */
   106 public class Package implements java.lang.reflect.AnnotatedElement {
   115 public class Package extends NamedPackage implements java.lang.reflect.AnnotatedElement {
   107     /**
   116     /**
   108      * Return the name of this package.
   117      * Return the name of this package.
   109      *
   118      *
   110      * @return  The fully-qualified name of this package as defined in section 6.5.3 of
   119      * @return  The fully-qualified name of this package as defined in section 6.5.3 of
   111      *          <cite>The Java&trade; Language Specification</cite>,
   120      *          <cite>The Java&trade; Language Specification</cite>,
   112      *          for example, {@code java.lang}
   121      *          for example, {@code java.lang}
   113      */
   122      */
   114     public String getName() {
   123     public String getName() {
   115         return pkgName;
   124         return packageName();
   116     }
   125     }
   117 
       
   118 
   126 
   119     /**
   127     /**
   120      * Return the title of the specification that this package implements.
   128      * Return the title of the specification that this package implements.
   121      * @return the specification title, null is returned if it is not known.
   129      * @return the specification title, {@code null} is returned if it is not known.
   122      */
   130      */
   123     public String getSpecificationTitle() {
   131     public String getSpecificationTitle() {
   124         return specTitle;
   132         return versionInfo.specTitle;
   125     }
   133     }
   126 
   134 
   127     /**
   135     /**
   128      * Returns the version number of the specification
   136      * Returns the version number of the specification
   129      * that this package implements.
   137      * that this package implements.
   130      * This version string must be a sequence of nonnegative decimal
   138      * This version string must be a sequence of non-negative decimal
   131      * integers separated by "."'s and may have leading zeros.
   139      * integers separated by "."'s and may have leading zeros.
   132      * When version strings are compared the most significant
   140      * When version strings are compared the most significant
   133      * numbers are compared.
   141      * numbers are compared.
   134      * @return the specification version, null is returned if it is not known.
   142      *
       
   143      *
       
   144      * <p>Specification version numbers use a syntax that consists of non-negative
       
   145      * decimal integers separated by periods ".", for example "2.0" or
       
   146      * "1.2.3.4.5.6.7".  This allows an extensible number to be used to represent
       
   147      * major, minor, micro, etc. versions.  The version specification is described
       
   148      * by the following formal grammar:
       
   149      * <blockquote>
       
   150      * <dl>
       
   151      * <dt><i>SpecificationVersion:</i>
       
   152      * <dd><i>Digits RefinedVersion<sub>opt</sub></i>
       
   153 
       
   154      * <dt><i>RefinedVersion:</i>
       
   155      * <dd>{@code .} <i>Digits</i>
       
   156      * <dd>{@code .} <i>Digits RefinedVersion</i>
       
   157      *
       
   158      * <dt><i>Digits:</i>
       
   159      * <dd><i>Digit</i>
       
   160      * <dd><i>Digits</i>
       
   161      *
       
   162      * <dt><i>Digit:</i>
       
   163      * <dd>any character for which {@link Character#isDigit} returns {@code true},
       
   164      * e.g. 0, 1, 2, ...
       
   165      * </dl>
       
   166      * </blockquote>
       
   167      *
       
   168      * @return the specification version, {@code null} is returned if it is not known.
   135      */
   169      */
   136     public String getSpecificationVersion() {
   170     public String getSpecificationVersion() {
   137         return specVersion;
   171         return versionInfo.specVersion;
   138     }
   172     }
   139 
   173 
   140     /**
   174     /**
   141      * Return the name of the organization, vendor,
   175      * Return the name of the organization, vendor,
   142      * or company that owns and maintains the specification
   176      * or company that owns and maintains the specification
   143      * of the classes that implement this package.
   177      * of the classes that implement this package.
   144      * @return the specification vendor, null is returned if it is not known.
   178      * @return the specification vendor, {@code null} is returned if it is not known.
   145      */
   179      */
   146     public String getSpecificationVendor() {
   180     public String getSpecificationVendor() {
   147         return specVendor;
   181         return versionInfo.specVendor;
   148     }
   182     }
   149 
   183 
   150     /**
   184     /**
   151      * Return the title of this package.
   185      * Return the title of this package.
   152      * @return the title of the implementation, null is returned if it is not known.
   186      * @return the title of the implementation, {@code null} is returned if it is not known.
   153      */
   187      */
   154     public String getImplementationTitle() {
   188     public String getImplementationTitle() {
   155         return implTitle;
   189         return versionInfo.implTitle;
   156     }
   190     }
   157 
   191 
   158     /**
   192     /**
   159      * Return the version of this implementation. It consists of any string
   193      * Return the version of this implementation. It consists of any string
   160      * assigned by the vendor of this implementation and does
   194      * assigned by the vendor of this implementation and does
   161      * not have any particular syntax specified or expected by the Java
   195      * not have any particular syntax specified or expected by the Java
   162      * runtime. It may be compared for equality with other
   196      * runtime. It may be compared for equality with other
   163      * package version strings used for this implementation
   197      * package version strings used for this implementation
   164      * by this vendor for this package.
   198      * by this vendor for this package.
   165      * @return the version of the implementation, null is returned if it is not known.
   199      * @return the version of the implementation, {@code null} is returned if it is not known.
   166      */
   200      */
   167     public String getImplementationVersion() {
   201     public String getImplementationVersion() {
   168         return implVersion;
   202         return versionInfo.implVersion;
   169     }
   203     }
   170 
   204 
   171     /**
   205     /**
   172      * Returns the name of the organization,
   206      * Returns the vendor that implemented this package, {@code null}
   173      * vendor or company that provided this implementation.
   207      * is returned if it is not known.
   174      * @return the vendor that implemented this package..
   208      * @return the vendor that implemented this package, {@code null}
       
   209      * is returned if it is not known.
   175      */
   210      */
   176     public String getImplementationVendor() {
   211     public String getImplementationVendor() {
   177         return implVendor;
   212         return versionInfo.implVendor;
   178     }
   213     }
   179 
   214 
   180     /**
   215     /**
   181      * Returns true if this package is sealed.
   216      * Returns true if this package is sealed.
   182      *
   217      *
   183      * @return true if the package is sealed, false otherwise
   218      * @return true if the package is sealed, false otherwise
   184      */
   219      */
   185     public boolean isSealed() {
   220     public boolean isSealed() {
   186         return sealBase != null;
   221         return module().isNamed() || versionInfo.sealBase != null;
   187     }
   222     }
   188 
   223 
   189     /**
   224     /**
   190      * Returns true if this package is sealed with respect to the specified
   225      * Returns true if this package is sealed with respect to the specified
   191      * code source url.
   226      * code source {@code url}.
   192      *
   227      *
   193      * @param url the code source url
   228      * @param url the code source URL
   194      * @return true if this package is sealed with respect to url
   229      * @return true if this package is sealed with respect to the given {@code url}
   195      */
   230      */
   196     public boolean isSealed(URL url) {
   231     public boolean isSealed(URL url) {
       
   232         Objects.requireNonNull(url);
       
   233 
       
   234         URL sealBase = null;
       
   235         if (versionInfo != VersionInfo.NULL_VERSION_INFO) {
       
   236             sealBase = versionInfo.sealBase;
       
   237         } else {
       
   238             try {
       
   239                 URI uri = location();
       
   240                 sealBase = uri != null ? uri.toURL() : null;
       
   241             } catch (MalformedURLException e) {
       
   242             }
       
   243         }
   197         return url.equals(sealBase);
   244         return url.equals(sealBase);
   198     }
   245     }
   199 
   246 
   200     /**
   247     /**
   201      * Compare this package's specification version with a
   248      * Compare this package's specification version with a
   214      *
   261      *
   215      * @param desired the version string of the desired version.
   262      * @param desired the version string of the desired version.
   216      * @return true if this package's version number is greater
   263      * @return true if this package's version number is greater
   217      *          than or equal to the desired version number
   264      *          than or equal to the desired version number
   218      *
   265      *
   219      * @exception NumberFormatException if the desired or current version
   266      * @exception NumberFormatException if the current version is not known or
   220      *          is not of the correct dotted form.
   267      *          the desired or current version is not of the correct dotted form.
   221      */
   268      */
   222     public boolean isCompatibleWith(String desired)
   269     public boolean isCompatibleWith(String desired)
   223         throws NumberFormatException
   270         throws NumberFormatException
   224     {
   271     {
   225         if (specVersion == null || specVersion.length() < 1) {
   272         if (versionInfo.specVersion == null || versionInfo.specVersion.length() < 1) {
   226             throw new NumberFormatException("Empty version string");
   273             throw new NumberFormatException("Empty version string");
   227         }
   274         }
   228 
   275 
   229         String [] sa = specVersion.split("\\.", -1);
   276         String [] sa = versionInfo.specVersion.split("\\.", -1);
   230         int [] si = new int[sa.length];
   277         int [] si = new int[sa.length];
   231         for (int i = 0; i < sa.length; i++) {
   278         for (int i = 0; i < sa.length; i++) {
   232             si[i] = Integer.parseInt(sa[i]);
   279             si[i] = Integer.parseInt(sa[i]);
   233             if (si[i] < 0)
   280             if (si[i] < 0)
   234                 throw NumberFormatException.forInputString("" + si[i]);
   281                 throw NumberFormatException.forInputString("" + si[i]);
   253         }
   300         }
   254         return true;
   301         return true;
   255     }
   302     }
   256 
   303 
   257     /**
   304     /**
   258      * Find a package by name in the callers {@code ClassLoader} instance.
   305      * Finds a package by name in the caller's class loader and its
   259      * The callers {@code ClassLoader} instance is used to find the package
   306      * ancestors.
   260      * instance corresponding to the named class. If the callers
   307      * <p>
   261      * {@code ClassLoader} instance is null then the set of packages loaded
   308      * If the caller's class loader defines a {@code Package} of the given name,
   262      * by the system {@code ClassLoader} instance is searched to find the
   309      * the {@code Package} is returned. Otherwise, the ancestors of the
   263      * named package. <p>
   310      * caller's class loader are searched recursively (parent by parent)
   264      *
   311      * for a {@code Package} of the given name.
   265      * Packages have attributes for versions and specifications only if the class
   312      * <p>
   266      * loader created the package instance with the appropriate attributes. Typically,
   313      * Calling this method is equivalent to calling {@link ClassLoader#getPackage}
   267      * those attributes are defined in the manifests that accompany the classes.
   314      * on a {@code ClassLoader} instance which is the caller's class loader.
   268      *
   315      *
   269      * @param name a package name, for example, java.lang.
   316      * @param name A package name, such as "{@code java.lang}".
   270      * @return the package of the requested name. It may be null if no package
   317      * @return The {@code Package} of the given name defined by the caller's
   271      *          information is available from the archive or codebase.
   318      *         class loader or its ancestors, or {@code null} if not found.
       
   319      *
       
   320      * @deprecated
       
   321      * If multiple class loaders delegate to each other and define classes
       
   322      * with the same package name, and one such loader relies on the lookup
       
   323      * behavior of {@code getPackage} to return a {@code Package} from
       
   324      * a parent loader, then the properties exposed by the {@code Package}
       
   325      * may not be as expected in the rest of the program.
       
   326      * For example, the {@code Package} will only expose annotations from the
       
   327      * {@code package-info.class} file defined by the parent loader, even if
       
   328      * annotations exist in a {@code package-info.class} file defined by
       
   329      * a child loader.  A more robust approach is to use the
       
   330      * {@link ClassLoader#getDefinedPackage} method which returns
       
   331      * a {@code Package} for the specified class loader.
       
   332      *
       
   333      * @see ClassLoader#getDefinedPackage
   272      */
   334      */
   273     @CallerSensitive
   335     @CallerSensitive
       
   336     @Deprecated
       
   337     @SuppressWarnings("deprecation")
   274     public static Package getPackage(String name) {
   338     public static Package getPackage(String name) {
   275         ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass());
   339         ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass());
   276         if (l != null) {
   340         return l != null ? l.getPackage(name) : BootLoader.getDefinedPackage(name);
   277             return l.getPackage(name);
   341     }
   278         } else {
   342 
   279             return getSystemPackage(name);
   343     /**
   280         }
   344      * Returns all of the {@code Package}s defined by the caller's class loader
   281     }
   345      * and its ancestors.  The returned array may contain more than one
   282 
   346      * {@code Package} object of the same package name, each defined by
   283     /**
   347      * a different class loader in the class loader hierarchy.
   284      * Get all the packages currently known for the caller's {@code ClassLoader}
   348      * <p>
   285      * instance.  Those packages correspond to classes loaded via or accessible by
   349      * Calling this method is equivalent to calling {@link ClassLoader#getPackages}
   286      * name to that {@code ClassLoader} instance.  If the caller's
   350      * on a {@code ClassLoader} instance which is the caller's class loader.
   287      * {@code ClassLoader} instance is the bootstrap {@code ClassLoader}
   351      *
   288      * instance, which may be represented by {@code null} in some implementations,
   352      * @return  The array of {@code Package} objects defined by this
   289      * only packages corresponding to classes loaded by the bootstrap
   353      *          class loader and its ancestors
   290      * {@code ClassLoader} instance will be returned.
   354      *
   291      *
   355      * @see ClassLoader#getDefinedPackages
   292      * @return a new array of packages known to the callers {@code ClassLoader}
       
   293      * instance.  An zero length array is returned if none are known.
       
   294      */
   356      */
   295     @CallerSensitive
   357     @CallerSensitive
   296     public static Package[] getPackages() {
   358     public static Package[] getPackages() {
   297         ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass());
   359         ClassLoader cl = ClassLoader.getClassLoader(Reflection.getCallerClass());
   298         if (l != null) {
   360         return cl != null ? cl.getPackages() : BootLoader.packages().toArray(Package[]::new);
   299             return l.getPackages();
       
   300         } else {
       
   301             return getSystemPackages();
       
   302         }
       
   303     }
       
   304 
       
   305     /**
       
   306      * Get the package for the specified class.
       
   307      * The class's class loader is used to find the package instance
       
   308      * corresponding to the specified class. If the class loader
       
   309      * is the bootstrap class loader, which may be represented by
       
   310      * {@code null} in some implementations, then the set of packages
       
   311      * loaded by the bootstrap class loader is searched to find the package.
       
   312      * <p>
       
   313      * Packages have attributes for versions and specifications only
       
   314      * if the class loader created the package
       
   315      * instance with the appropriate attributes. Typically those
       
   316      * attributes are defined in the manifests that accompany
       
   317      * the classes.
       
   318      *
       
   319      * @param c the class to get the package of.
       
   320      * @return the package of the class. It may be null if no package
       
   321      *          information is available from the archive or codebase.  */
       
   322     static Package getPackage(Class<?> c) {
       
   323         String name = c.getName();
       
   324         int i = name.lastIndexOf('.');
       
   325         if (i != -1) {
       
   326             name = name.substring(0, i);
       
   327             ClassLoader cl = c.getClassLoader();
       
   328             if (cl != null) {
       
   329                 return cl.getPackage(name);
       
   330             } else {
       
   331                 return getSystemPackage(name);
       
   332             }
       
   333         } else {
       
   334             return null;
       
   335         }
       
   336     }
   361     }
   337 
   362 
   338     /**
   363     /**
   339      * Return the hash code computed from the package name.
   364      * Return the hash code computed from the package name.
   340      * @return the hash code computed from the package name.
   365      * @return the hash code computed from the package name.
   341      */
   366      */
       
   367     @Override
   342     public int hashCode(){
   368     public int hashCode(){
   343         return pkgName.hashCode();
   369         return packageName().hashCode();
   344     }
   370     }
   345 
   371 
   346     /**
   372     /**
   347      * Returns the string representation of this Package.
   373      * Returns the string representation of this Package.
   348      * Its value is the string "package " and the package name.
   374      * Its value is the string "package " and the package name.
   349      * If the package title is defined it is appended.
   375      * If the package title is defined it is appended.
   350      * If the package version is defined it is appended.
   376      * If the package version is defined it is appended.
   351      * @return the string representation of the package.
   377      * @return the string representation of the package.
   352      */
   378      */
       
   379     @Override
   353     public String toString() {
   380     public String toString() {
   354         String spec = specTitle;
   381         String spec = versionInfo.specTitle;
   355         String ver =  specVersion;
   382         String ver =  versionInfo.specVersion;
   356         if (spec != null && spec.length() > 0)
   383         if (spec != null && spec.length() > 0)
   357             spec = ", " + spec;
   384             spec = ", " + spec;
   358         else
   385         else
   359             spec = "";
   386             spec = "";
   360         if (ver != null && ver.length() > 0)
   387         if (ver != null && ver.length() > 0)
   361             ver = ", version " + ver;
   388             ver = ", version " + ver;
   362         else
   389         else
   363             ver = "";
   390             ver = "";
   364         return "package " + pkgName + spec + ver;
   391         return "package " + packageName() + spec + ver;
   365     }
   392     }
   366 
   393 
   367     private Class<?> getPackageInfo() {
   394     private Class<?> getPackageInfo() {
   368         if (packageInfo == null) {
   395         if (packageInfo == null) {
   369             try {
   396             // find package-info.class defined by loader
   370                 packageInfo = Class.forName(pkgName + ".package-info", false, loader);
   397             String cn = packageName() + ".package-info";
   371             } catch (ClassNotFoundException ex) {
   398             PrivilegedAction<ClassLoader> pa = module()::getClassLoader;
       
   399             ClassLoader loader = AccessController.doPrivileged(pa);
       
   400             Class<?> c = loader != null ? loader.loadLocalClass(cn)
       
   401                                         : BootLoader.loadClassOrNull(cn);
       
   402             if (c != null) {
       
   403                 packageInfo = c;
       
   404             } else {
   372                 // store a proxy for the package info that has no annotations
   405                 // store a proxy for the package info that has no annotations
   373                 class PackageInfoProxy {}
   406                 class PackageInfoProxy {}
   374                 packageInfo = PackageInfoProxy.class;
   407                 packageInfo = PackageInfoProxy.class;
   375             }
   408             }
   376         }
   409         }
   435     public Annotation[] getDeclaredAnnotations()  {
   468     public Annotation[] getDeclaredAnnotations()  {
   436         return getPackageInfo().getDeclaredAnnotations();
   469         return getPackageInfo().getDeclaredAnnotations();
   437     }
   470     }
   438 
   471 
   439     /**
   472     /**
   440      * Construct a package instance with the specified version
   473      * Construct a package instance for an unnamed module
   441      * information.
   474      * with the specified version information.
       
   475      *
       
   476      * @apiNote
       
   477      * This method should not be called to define a Package for named module.
       
   478      *
   442      * @param name the name of the package
   479      * @param name the name of the package
   443      * @param spectitle the title of the specification
   480      * @param spectitle the title of the specification
   444      * @param specversion the version of the specification
   481      * @param specversion the version of the specification
   445      * @param specvendor the organization that maintains the specification
   482      * @param specvendor the organization that maintains the specification
   446      * @param impltitle the title of the implementation
   483      * @param impltitle the title of the implementation
   447      * @param implversion the version of the implementation
   484      * @param implversion the version of the implementation
   448      * @param implvendor the organization that maintains the implementation
   485      * @param implvendor the organization that maintains the implementation
       
   486      * @param sealbase code source where this Package comes from
       
   487      * @param loader defining class loader
   449      */
   488      */
   450     Package(String name,
   489     Package(String name,
   451             String spectitle, String specversion, String specvendor,
   490             String spectitle, String specversion, String specvendor,
   452             String impltitle, String implversion, String implvendor,
   491             String impltitle, String implversion, String implvendor,
   453             URL sealbase, ClassLoader loader)
   492             URL sealbase, ClassLoader loader)
   454     {
   493     {
   455         pkgName = name;
   494         super(Objects.requireNonNull(name),
   456         implTitle = impltitle;
   495               loader != null ? loader.getUnnamedModule()
   457         implVersion = implversion;
   496                              : BootLoader.getUnnamedModule());
   458         implVendor = implvendor;
   497 
   459         specTitle = spectitle;
   498         this.versionInfo = VersionInfo.getInstance(spectitle, specversion,
   460         specVersion = specversion;
   499                                                    specvendor, impltitle,
   461         specVendor = specvendor;
   500                                                    implversion, implvendor,
   462         sealBase = sealbase;
   501                                                    sealbase);
   463         this.loader = loader;
   502     }
       
   503 
       
   504     Package(String name, Module module) {
       
   505         super(name, module);
       
   506         this.versionInfo = VersionInfo.NULL_VERSION_INFO;
   464     }
   507     }
   465 
   508 
   466     /*
   509     /*
   467      * Construct a package using the attributes from the specified manifest.
   510      * Versioning information.  Only for packages in unnamed modules.
   468      *
   511      */
   469      * @param name the package name
   512     static class VersionInfo {
   470      * @param man the optional manifest for the package
   513         static final VersionInfo NULL_VERSION_INFO
   471      * @param url the optional code source url for the package
   514             = new VersionInfo(null, null, null, null, null, null, null);
   472      */
   515 
   473     private Package(String name, Manifest man, URL url, ClassLoader loader) {
   516         private final String specTitle;
   474         String path = name.replace('.', '/').concat("/");
   517         private final String specVersion;
   475         String sealed = null;
   518         private final String specVendor;
   476         String specTitle= null;
   519         private final String implTitle;
   477         String specVersion= null;
   520         private final String implVersion;
   478         String specVendor= null;
   521         private final String implVendor;
   479         String implTitle= null;
   522         private final URL sealBase;
   480         String implVersion= null;
   523 
   481         String implVendor= null;
   524         static VersionInfo getInstance(String spectitle, String specversion,
   482         URL sealBase= null;
   525                                        String specvendor, String impltitle,
   483         Attributes attr = man.getAttributes(path);
   526                                        String implversion, String implvendor,
   484         if (attr != null) {
   527                                        URL sealbase) {
   485             specTitle   = attr.getValue(Name.SPECIFICATION_TITLE);
   528             if (spectitle == null && specversion == null &&
   486             specVersion = attr.getValue(Name.SPECIFICATION_VERSION);
   529                     specvendor == null && impltitle == null &&
   487             specVendor  = attr.getValue(Name.SPECIFICATION_VENDOR);
   530                     implvendor == null && sealbase == null) {
   488             implTitle   = attr.getValue(Name.IMPLEMENTATION_TITLE);
   531                 return NULL_VERSION_INFO;
   489             implVersion = attr.getValue(Name.IMPLEMENTATION_VERSION);
       
   490             implVendor  = attr.getValue(Name.IMPLEMENTATION_VENDOR);
       
   491             sealed      = attr.getValue(Name.SEALED);
       
   492         }
       
   493         attr = man.getMainAttributes();
       
   494         if (attr != null) {
       
   495             if (specTitle == null) {
       
   496                 specTitle = attr.getValue(Name.SPECIFICATION_TITLE);
       
   497             }
   532             }
   498             if (specVersion == null) {
   533             return new VersionInfo(spectitle, specversion, specvendor,
   499                 specVersion = attr.getValue(Name.SPECIFICATION_VERSION);
   534                     impltitle, implversion, implvendor,
   500             }
   535                     sealbase);
   501             if (specVendor == null) {
   536         }
   502                 specVendor = attr.getValue(Name.SPECIFICATION_VENDOR);
   537 
   503             }
   538         private VersionInfo(String spectitle, String specversion,
   504             if (implTitle == null) {
   539                             String specvendor, String impltitle,
   505                 implTitle = attr.getValue(Name.IMPLEMENTATION_TITLE);
   540                             String implversion, String implvendor,
   506             }
   541                             URL sealbase)
   507             if (implVersion == null) {
   542         {
   508                 implVersion = attr.getValue(Name.IMPLEMENTATION_VERSION);
   543             this.implTitle = impltitle;
   509             }
   544             this.implVersion = implversion;
   510             if (implVendor == null) {
   545             this.implVendor = implvendor;
   511                 implVendor = attr.getValue(Name.IMPLEMENTATION_VENDOR);
   546             this.specTitle = spectitle;
   512             }
   547             this.specVersion = specversion;
   513             if (sealed == null) {
   548             this.specVendor = specvendor;
   514                 sealed = attr.getValue(Name.SEALED);
   549             this.sealBase = sealbase;
   515             }
   550         }
   516         }
   551     }
   517         if ("true".equalsIgnoreCase(sealed)) {
   552 
   518             sealBase = url;
   553     private final VersionInfo versionInfo;
   519         }
   554     private Class<?> packageInfo;
   520         pkgName = name;
       
   521         this.specTitle = specTitle;
       
   522         this.specVersion = specVersion;
       
   523         this.specVendor = specVendor;
       
   524         this.implTitle = implTitle;
       
   525         this.implVersion = implVersion;
       
   526         this.implVendor = implVendor;
       
   527         this.sealBase = sealBase;
       
   528         this.loader = loader;
       
   529     }
       
   530 
       
   531     /*
       
   532      * Returns the loaded system package for the specified name.
       
   533      */
       
   534     static Package getSystemPackage(String name) {
       
   535         Package pkg = pkgs.get(name);
       
   536         if (pkg == null) {
       
   537             name = name.replace('.', '/').concat("/");
       
   538             String fn = getSystemPackage0(name);
       
   539             if (fn != null) {
       
   540                 pkg = defineSystemPackage(name, fn);
       
   541             }
       
   542         }
       
   543         return pkg;
       
   544     }
       
   545 
       
   546     /*
       
   547      * Return an array of loaded system packages.
       
   548      */
       
   549     static Package[] getSystemPackages() {
       
   550         // First, update the system package map with new package names
       
   551         String[] names = getSystemPackages0();
       
   552         for (String name : names) {
       
   553             if (!pkgs.containsKey(name)) {
       
   554                 defineSystemPackage(name, getSystemPackage0(name));
       
   555             }
       
   556         }
       
   557         return pkgs.values().toArray(new Package[pkgs.size()]);
       
   558     }
       
   559 
       
   560     private static Package defineSystemPackage(final String iname,
       
   561                                                final String fn)
       
   562     {
       
   563         // Convert to "."-separated package name
       
   564         String name = iname.substring(0, iname.length() - 1).replace('/', '.');
       
   565         // Creates a cached manifest for the file name, allowing
       
   566         // only-once, lazy reads of manifest from jar files
       
   567         CachedManifest cachedManifest = createCachedManifest(fn);
       
   568         pkgs.putIfAbsent(name, new Package(name, cachedManifest.getManifest(),
       
   569                                            cachedManifest.getURL(), null));
       
   570         // Ensure we only expose one Package object
       
   571         return pkgs.get(name);
       
   572     }
       
   573 
       
   574     private static CachedManifest createCachedManifest(String fn) {
       
   575         if (!manifests.containsKey(fn)) {
       
   576             manifests.putIfAbsent(fn, new CachedManifest(fn));
       
   577         }
       
   578         return manifests.get(fn);
       
   579     }
       
   580 
       
   581     // The map of loaded system packages
       
   582     private static final ConcurrentHashMap<String, Package> pkgs
       
   583             = new ConcurrentHashMap<>();
       
   584 
       
   585     // Maps each directory or zip file name to its corresponding manifest, if
       
   586     // it exists
       
   587     private static final ConcurrentHashMap<String, CachedManifest> manifests
       
   588             = new ConcurrentHashMap<>();
       
   589 
       
   590     private static class CachedManifest {
       
   591         private static final Manifest EMPTY_MANIFEST = new Manifest();
       
   592         private final String fileName;
       
   593         private final URL url;
       
   594         private volatile Manifest manifest;
       
   595 
       
   596         CachedManifest(final String fileName) {
       
   597             this.fileName = fileName;
       
   598             this.url = AccessController.doPrivileged(new PrivilegedAction<>() {
       
   599                 public URL run() {
       
   600                     final File file = new File(fileName);
       
   601                     if (file.isFile()) {
       
   602                         try {
       
   603                             return ParseUtil.fileToEncodedURL(file);
       
   604                         } catch (MalformedURLException e) {
       
   605                         }
       
   606                     }
       
   607                     return null;
       
   608                 }
       
   609             });
       
   610         }
       
   611 
       
   612         public URL getURL() {
       
   613             return url;
       
   614         }
       
   615 
       
   616         public Manifest getManifest() {
       
   617             if (url == null) {
       
   618                 return EMPTY_MANIFEST;
       
   619             }
       
   620             Manifest m = manifest;
       
   621             if (m != null) {
       
   622                 return m;
       
   623             }
       
   624             synchronized (this) {
       
   625                 m = manifest;
       
   626                 if (m != null) {
       
   627                     return m;
       
   628                 }
       
   629                 m = AccessController.doPrivileged(new PrivilegedAction<>() {
       
   630                     public Manifest run() {
       
   631                         try (FileInputStream fis = new FileInputStream(fileName);
       
   632                              JarInputStream jis = new JarInputStream(fis, false)) {
       
   633                             return jis.getManifest();
       
   634                         } catch (IOException e) {
       
   635                             return null;
       
   636                         }
       
   637                     }
       
   638                 });
       
   639                 manifest = m = (m == null ? EMPTY_MANIFEST : m);
       
   640             }
       
   641             return m;
       
   642         }
       
   643     }
       
   644 
       
   645     private static native String getSystemPackage0(String name);
       
   646     private static native String[] getSystemPackages0();
       
   647 
       
   648     /*
       
   649      * Private storage for the package name and attributes.
       
   650      */
       
   651     private final String pkgName;
       
   652     private final String specTitle;
       
   653     private final String specVersion;
       
   654     private final String specVendor;
       
   655     private final String implTitle;
       
   656     private final String implVersion;
       
   657     private final String implVendor;
       
   658     private final URL sealBase;
       
   659     private final transient ClassLoader loader;
       
   660     private transient Class<?> packageInfo;
       
   661 }
   555 }