1 /*
   2  * Copyright (c) 1997, 2018, 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;
  27 
  28 import java.lang.annotation.Annotation;
  29 import java.lang.reflect.AnnotatedElement;
  30 import java.net.MalformedURLException;
  31 import java.net.URI;
  32 import java.net.URL;
  33 import java.security.AccessController;
  34 import java.security.PrivilegedAction;
  35 import java.util.Objects;
  36 
  37 import jdk.internal.loader.BootLoader;
  38 import jdk.internal.reflect.CallerSensitive;
  39 import jdk.internal.reflect.Reflection;
  40 
  41 
  42 /**
  43  * Represents metadata about a run-time package associated with a class loader.
  44  * Metadata includes annotations, versioning, and sealing.
  45  * <p>
  46  * Annotations for the run-time package are read from {@code package-info.class}
  47  * at the same code source as classes in the run-time package.
  48  * <p>
  49  * The set of classes that make up the run-time package may implement a
  50  * particular specification. The specification title, version, and vendor
  51  * (indicating the owner/maintainer of the specification) can be provided
  52  * when the {@code Package} is defined. An application can ask if the
  53  * {@code Package} is compatible with a particular specification version
  54  * by using the {@link #isCompatibleWith Package.isCompatibleWith(String)}
  55  * method. In addition, information about the actual classes that make up the
  56  * run-time package can be provided when the Package is defined.
  57  * This information consists of an implementation title, version, and vendor
  58  * (indicating the supplier of the classes).
  59  * <p>
  60  * A {@code Package} may be explicitly defined with
  61  * the {@link ClassLoader#definePackage(String, String, String, String,
  62  * String, String, String, URL)} method.
  63  * The caller supplies the specification and implementation titles, versions, and
  64  * vendors. The caller also indicates whether the package is
  65  * {@linkplain java.util.jar.Attributes.Name#SEALED sealed}.
  66  * If a {@code Package} is not explicitly defined for a run-time package when
  67  * a class in that run-time package is defined, then a {@code Package} is
  68  * automatically defined by the class's defining class loader, as follows.
  69  * <p>
  70  * A {@code Package} automatically defined for classes in a named module has
  71  * the following properties:
  72  * <ul>
  73  * <li>The name of the package is derived from the {@linkplain Class#getName() binary names}
  74  *     of the classes. Since classes in a named module must be in a named package,
  75  *     the derived name is never empty.</li>
  76  * <li>The package is sealed with the {@linkplain java.lang.module.ModuleReference#location()
  77  *     module location} as the code source, if known.</li>
  78  * <li>The specification and implementation titles, versions, and vendors
  79  *     are unspecified.</li>
  80  * <li>Any annotations on the package are read from {@code package-info.class}
  81  *     as specified above.</li>
  82  * </ul>
  83  * <p>
  84  * A {@code Package} automatically defined for classes in an unnamed module
  85  * has the following properties:
  86  * <ul>
  87  * <li>The name of the package is either {@code ""} (for classes in an unnamed package)
  88  *     or derived from the {@linkplain Class#getName() binary names} of the classes
  89  *     (for classes in a named package).</li>
  90  * <li>The package is not sealed.</li>
  91  * <li>The specification and implementation titles, versions, and vendors
  92  *     are unspecified.</li>
  93  * <li>Any annotations on the package are read from {@code package-info.class}
  94  *     as specified above.</li>
  95  * </ul>
  96  *
  97  * <p>
  98  * A {@code Package} can be obtained with the {@link Package#getPackage
  99  * Package.getPackage(String)} and {@link ClassLoader#getDefinedPackage
 100  * ClassLoader.getDefinedPackage(String)} methods.
 101  * Every {@code Package} defined by a class loader can be obtained
 102  * with the {@link Package#getPackages Package.getPackages()} and
 103  * {@link ClassLoader#getDefinedPackages} methods.
 104  *
 105  * @implNote
 106  * The <a href="ClassLoader.html#builtinLoaders">builtin class loaders</a>
 107  * do not explicitly define {@code Package} objects for packages in
 108  * <em>named modules</em>.  Instead those packages are automatically defined
 109  * and have no specification and implementation versioning information.
 110  *
 111  * @jvms 5.3 Run-time package
 112  * @see <a href="{@docRoot}/../specs/jar/jar.html#package-sealing">
 113  * The JAR File Specification: Package Sealing</a>
 114  * @see ClassLoader#definePackage(String, String, String, String, String, String, String, URL)
 115  *
 116  * @since 1.2
 117  * @revised 9
 118  * @spec JPMS
 119  */
 120 public class Package extends NamedPackage implements java.lang.reflect.AnnotatedElement {
 121     /**
 122      * Return the name of this package.
 123      *
 124      * @return  The fully-qualified name of this package as defined in section 6.5.3 of
 125      *          <cite>The Java&trade; Language Specification</cite>,
 126      *          for example, {@code java.lang}
 127      */
 128     public String getName() {
 129         return packageName();
 130     }
 131 
 132     /**
 133      * Return the title of the specification that this package implements.
 134      * @return the specification title, {@code null} is returned if it is not known.
 135      */
 136     public String getSpecificationTitle() {
 137         return versionInfo.specTitle;
 138     }
 139 
 140     /**
 141      * Returns the version number of the specification
 142      * that this package implements.
 143      * This version string must be a sequence of non-negative decimal
 144      * integers separated by "."'s and may have leading zeros.
 145      * When version strings are compared the most significant
 146      * numbers are compared.
 147      *
 148      *
 149      * <p>Specification version numbers use a syntax that consists of non-negative
 150      * decimal integers separated by periods ".", for example "2.0" or
 151      * "1.2.3.4.5.6.7".  This allows an extensible number to be used to represent
 152      * major, minor, micro, etc. versions.  The version specification is described
 153      * by the following formal grammar:
 154      * <blockquote>
 155      * <dl>
 156      * <dt><i>SpecificationVersion:</i>
 157      * <dd><i>Digits RefinedVersion<sub>opt</sub></i>
 158 
 159      * <dt><i>RefinedVersion:</i>
 160      * <dd>{@code .} <i>Digits</i>
 161      * <dd>{@code .} <i>Digits RefinedVersion</i>
 162      *
 163      * <dt><i>Digits:</i>
 164      * <dd><i>Digit</i>
 165      * <dd><i>Digits</i>
 166      *
 167      * <dt><i>Digit:</i>
 168      * <dd>any character for which {@link Character#isDigit} returns {@code true},
 169      * e.g. 0, 1, 2, ...
 170      * </dl>
 171      * </blockquote>
 172      *
 173      * @return the specification version, {@code null} is returned if it is not known.
 174      */
 175     public String getSpecificationVersion() {
 176         return versionInfo.specVersion;
 177     }
 178 
 179     /**
 180      * Return the name of the organization, vendor,
 181      * or company that owns and maintains the specification
 182      * of the classes that implement this package.
 183      * @return the specification vendor, {@code null} is returned if it is not known.
 184      */
 185     public String getSpecificationVendor() {
 186         return versionInfo.specVendor;
 187     }
 188 
 189     /**
 190      * Return the title of this package.
 191      * @return the title of the implementation, {@code null} is returned if it is not known.
 192      */
 193     public String getImplementationTitle() {
 194         return versionInfo.implTitle;
 195     }
 196 
 197     /**
 198      * Return the version of this implementation. It consists of any string
 199      * assigned by the vendor of this implementation and does
 200      * not have any particular syntax specified or expected by the Java
 201      * runtime. It may be compared for equality with other
 202      * package version strings used for this implementation
 203      * by this vendor for this package.
 204      * @return the version of the implementation, {@code null} is returned if it is not known.
 205      */
 206     public String getImplementationVersion() {
 207         return versionInfo.implVersion;
 208     }
 209 
 210     /**
 211      * Returns the vendor that implemented this package, {@code null}
 212      * is returned if it is not known.
 213      * @return the vendor that implemented this package, {@code null}
 214      * is returned if it is not known.
 215      *
 216      * @revised 9
 217      * @spec JPMS
 218      */
 219     public String getImplementationVendor() {
 220         return versionInfo.implVendor;
 221     }
 222 
 223     /**
 224      * Returns true if this package is sealed.
 225      *
 226      * @return true if the package is sealed, false otherwise
 227      */
 228     public boolean isSealed() {
 229         return module().isNamed() || versionInfo.sealBase != null;
 230     }
 231 
 232     /**
 233      * Returns true if this package is sealed with respect to the specified
 234      * code source {@code url}.
 235      *
 236      * @param url the code source URL
 237      * @return true if this package is sealed with respect to the given {@code url}
 238      */
 239     public boolean isSealed(URL url) {
 240         Objects.requireNonNull(url);
 241 
 242         URL sealBase = null;
 243         if (versionInfo != VersionInfo.NULL_VERSION_INFO) {
 244             sealBase = versionInfo.sealBase;
 245         } else {
 246             try {
 247                 URI uri = location();
 248                 sealBase = uri != null ? uri.toURL() : null;
 249             } catch (MalformedURLException e) {
 250             }
 251         }
 252         return url.equals(sealBase);
 253     }
 254 
 255     /**
 256      * Compare this package's specification version with a
 257      * desired version. It returns true if
 258      * this packages specification version number is greater than or equal
 259      * to the desired version number. <p>
 260      *
 261      * Version numbers are compared by sequentially comparing corresponding
 262      * components of the desired and specification strings.
 263      * Each component is converted as a decimal integer and the values
 264      * compared.
 265      * If the specification value is greater than the desired
 266      * value true is returned. If the value is less false is returned.
 267      * If the values are equal the period is skipped and the next pair of
 268      * components is compared.
 269      *
 270      * @param desired the version string of the desired version.
 271      * @return true if this package's version number is greater
 272      *          than or equal to the desired version number
 273      *
 274      * @exception NumberFormatException if the current version is not known or
 275      *          the desired or current version is not of the correct dotted form.
 276      */
 277     public boolean isCompatibleWith(String desired)
 278         throws NumberFormatException
 279     {
 280         if (versionInfo.specVersion == null || versionInfo.specVersion.length() < 1) {
 281             throw new NumberFormatException("Empty version string");
 282         }
 283 
 284         String [] sa = versionInfo.specVersion.split("\\.", -1);
 285         int [] si = new int[sa.length];
 286         for (int i = 0; i < sa.length; i++) {
 287             si[i] = Integer.parseInt(sa[i]);
 288             if (si[i] < 0)
 289                 throw NumberFormatException.forInputString("" + si[i], 10);
 290         }
 291 
 292         String [] da = desired.split("\\.", -1);
 293         int [] di = new int[da.length];
 294         for (int i = 0; i < da.length; i++) {
 295             di[i] = Integer.parseInt(da[i]);
 296             if (di[i] < 0)
 297                 throw NumberFormatException.forInputString("" + di[i], 10);
 298         }
 299 
 300         int len = Math.max(di.length, si.length);
 301         for (int i = 0; i < len; i++) {
 302             int d = (i < di.length ? di[i] : 0);
 303             int s = (i < si.length ? si[i] : 0);
 304             if (s < d)
 305                 return false;
 306             if (s > d)
 307                 return true;
 308         }
 309         return true;
 310     }
 311 
 312     /**
 313      * Finds a package by name in the caller's class loader and its
 314      * ancestors.
 315      * <p>
 316      * If the caller's class loader defines a {@code Package} of the given name,
 317      * the {@code Package} is returned. Otherwise, the ancestors of the
 318      * caller's class loader are searched recursively (parent by parent)
 319      * for a {@code Package} of the given name.
 320      * <p>
 321      * Calling this method is equivalent to calling {@link ClassLoader#getPackage}
 322      * on a {@code ClassLoader} instance which is the caller's class loader.
 323      *
 324      * @param name A package name, such as "{@code java.lang}".
 325      * @return The {@code Package} of the given name defined by the caller's
 326      *         class loader or its ancestors, or {@code null} if not found.
 327      *
 328      * @throws NullPointerException
 329      *         if {@code name} is {@code null}.
 330      *
 331      * @deprecated
 332      * If multiple class loaders delegate to each other and define classes
 333      * with the same package name, and one such loader relies on the lookup
 334      * behavior of {@code getPackage} to return a {@code Package} from
 335      * a parent loader, then the properties exposed by the {@code Package}
 336      * may not be as expected in the rest of the program.
 337      * For example, the {@code Package} will only expose annotations from the
 338      * {@code package-info.class} file defined by the parent loader, even if
 339      * annotations exist in a {@code package-info.class} file defined by
 340      * a child loader.  A more robust approach is to use the
 341      * {@link ClassLoader#getDefinedPackage} method which returns
 342      * a {@code Package} for the specified class loader.
 343      *
 344      * @see ClassLoader#getDefinedPackage
 345      *
 346      * @revised 9
 347      * @spec JPMS
 348      */
 349     @CallerSensitive
 350     @Deprecated(since="9")
 351     @SuppressWarnings("deprecation")
 352     public static Package getPackage(String name) {
 353         ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass());
 354         return l != null ? l.getPackage(name) : BootLoader.getDefinedPackage(name);
 355     }
 356 
 357     /**
 358      * Returns all of the {@code Package}s defined by the caller's class loader
 359      * and its ancestors.  The returned array may contain more than one
 360      * {@code Package} object of the same package name, each defined by
 361      * a different class loader in the class loader hierarchy.
 362      * <p>
 363      * Calling this method is equivalent to calling {@link ClassLoader#getPackages}
 364      * on a {@code ClassLoader} instance which is the caller's class loader.
 365      *
 366      * @return  The array of {@code Package} objects defined by this
 367      *          class loader and its ancestors
 368      *
 369      * @see ClassLoader#getDefinedPackages
 370      *
 371      * @revised 9
 372      * @spec JPMS
 373      */
 374     @CallerSensitive
 375     public static Package[] getPackages() {
 376         ClassLoader cl = ClassLoader.getClassLoader(Reflection.getCallerClass());
 377         return cl != null ? cl.getPackages() : BootLoader.packages().toArray(Package[]::new);
 378     }
 379 
 380     /**
 381      * Return the hash code computed from the package name.
 382      * @return the hash code computed from the package name.
 383      */
 384     @Override
 385     public int hashCode(){
 386         return packageName().hashCode();
 387     }
 388 
 389     /**
 390      * Returns the string representation of this Package.
 391      * Its value is the string "package " and the package name.
 392      * If the package title is defined it is appended.
 393      * If the package version is defined it is appended.
 394      * @return the string representation of the package.
 395      */
 396     @Override
 397     public String toString() {
 398         String spec = versionInfo.specTitle;
 399         String ver =  versionInfo.specVersion;
 400         if (spec != null && !spec.isEmpty())
 401             spec = ", " + spec;
 402         else
 403             spec = "";
 404         if (ver != null && !ver.isEmpty())
 405             ver = ", version " + ver;
 406         else
 407             ver = "";
 408         return "package " + packageName() + spec + ver;
 409     }
 410 
 411     private Class<?> getPackageInfo() {
 412         if (packageInfo == null) {
 413             // find package-info.class defined by loader
 414             String cn = packageName() + ".package-info";
 415             Module module = module();
 416             PrivilegedAction<ClassLoader> pa = module::getClassLoader;
 417             ClassLoader loader = AccessController.doPrivileged(pa);
 418             Class<?> c;
 419             if (loader != null) {
 420                 c = loader.loadClass(module, cn);
 421             } else {
 422                 c = BootLoader.loadClass(module, cn);
 423             }
 424 
 425             if (c != null) {
 426                 packageInfo = c;
 427             } else {
 428                 // store a proxy for the package info that has no annotations
 429                 class PackageInfoProxy {}
 430                 packageInfo = PackageInfoProxy.class;
 431             }
 432         }
 433         return packageInfo;
 434     }
 435 
 436     /**
 437      * @throws NullPointerException {@inheritDoc}
 438      * @since 1.5
 439      */
 440     public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
 441         return getPackageInfo().getAnnotation(annotationClass);
 442     }
 443 
 444     /**
 445      * {@inheritDoc}
 446      * @throws NullPointerException {@inheritDoc}
 447      * @since 1.5
 448      */
 449     @Override
 450     public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
 451         return AnnotatedElement.super.isAnnotationPresent(annotationClass);
 452     }
 453 
 454     /**
 455      * @throws NullPointerException {@inheritDoc}
 456      * @since 1.8
 457      */
 458     @Override
 459     public  <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass) {
 460         return getPackageInfo().getAnnotationsByType(annotationClass);
 461     }
 462 
 463     /**
 464      * @since 1.5
 465      */
 466     public Annotation[] getAnnotations() {
 467         return getPackageInfo().getAnnotations();
 468     }
 469 
 470     /**
 471      * @throws NullPointerException {@inheritDoc}
 472      * @since 1.8
 473      */
 474     @Override
 475     public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
 476         return getPackageInfo().getDeclaredAnnotation(annotationClass);
 477     }
 478 
 479     /**
 480      * @throws NullPointerException {@inheritDoc}
 481      * @since 1.8
 482      */
 483     @Override
 484     public <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A> annotationClass) {
 485         return getPackageInfo().getDeclaredAnnotationsByType(annotationClass);
 486     }
 487 
 488     /**
 489      * @since 1.5
 490      */
 491     public Annotation[] getDeclaredAnnotations()  {
 492         return getPackageInfo().getDeclaredAnnotations();
 493     }
 494 
 495     /**
 496      * Construct a package instance for an unnamed module
 497      * with the specified version information.
 498      *
 499      * @apiNote
 500      * This method should not be called to define a Package for named module.
 501      *
 502      * @param name the name of the package
 503      * @param spectitle the title of the specification
 504      * @param specversion the version of the specification
 505      * @param specvendor the organization that maintains the specification
 506      * @param impltitle the title of the implementation
 507      * @param implversion the version of the implementation
 508      * @param implvendor the organization that maintains the implementation
 509      * @param sealbase code source where this Package comes from
 510      * @param loader defining class loader
 511      */
 512     Package(String name,
 513             String spectitle, String specversion, String specvendor,
 514             String impltitle, String implversion, String implvendor,
 515             URL sealbase, ClassLoader loader)
 516     {
 517         super(Objects.requireNonNull(name),
 518               loader != null ? loader.getUnnamedModule()
 519                              : BootLoader.getUnnamedModule());
 520 
 521         this.versionInfo = VersionInfo.getInstance(spectitle, specversion,
 522                                                    specvendor, impltitle,
 523                                                    implversion, implvendor,
 524                                                    sealbase);
 525     }
 526 
 527     Package(String name, Module module) {
 528         super(name, module);
 529         this.versionInfo = VersionInfo.NULL_VERSION_INFO;
 530     }
 531 
 532     /*
 533      * Versioning information.  Only for packages in unnamed modules.
 534      */
 535     static class VersionInfo {
 536         static final VersionInfo NULL_VERSION_INFO
 537             = new VersionInfo(null, null, null, null, null, null, null);
 538 
 539         private final String specTitle;
 540         private final String specVersion;
 541         private final String specVendor;
 542         private final String implTitle;
 543         private final String implVersion;
 544         private final String implVendor;
 545         private final URL sealBase;
 546 
 547         static VersionInfo getInstance(String spectitle, String specversion,
 548                                        String specvendor, String impltitle,
 549                                        String implversion, String implvendor,
 550                                        URL sealbase) {
 551             if (spectitle == null && specversion == null &&
 552                     specvendor == null && impltitle == null &&
 553                     implversion == null && implvendor == null &&
 554                     sealbase == null) {
 555                 return NULL_VERSION_INFO;
 556             }
 557             return new VersionInfo(spectitle, specversion, specvendor,
 558                     impltitle, implversion, implvendor,
 559                     sealbase);
 560         }
 561 
 562         private VersionInfo(String spectitle, String specversion,
 563                             String specvendor, String impltitle,
 564                             String implversion, String implvendor,
 565                             URL sealbase)
 566         {
 567             this.implTitle = impltitle;
 568             this.implVersion = implversion;
 569             this.implVendor = implvendor;
 570             this.specTitle = spectitle;
 571             this.specVersion = specversion;
 572             this.specVendor = specvendor;
 573             this.sealBase = sealbase;
 574         }
 575     }
 576 
 577     private final VersionInfo versionInfo;
 578     private Class<?> packageInfo;
 579 }