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