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 sun.reflect.CallerSensitive;
  40 import sun.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  */
 115 public class Package extends NamedPackage implements java.lang.reflect.AnnotatedElement {
 116     /**
 117      * Return the name of this package.
 118      *
 119      * @return  The fully-qualified name of this package as defined in section 6.5.3 of
 120      *          <cite>The Java&trade; Language Specification</cite>,
 121      *          for example, {@code java.lang}
 122      */
 123     public String getName() {
 124         return packageName();
 125     }
 126 
 127     /**
 128      * Return the title of the specification that this package implements.
 129      * @return the specification title, {@code null} is returned if it is not known.
 130      */
 131     public String getSpecificationTitle() {
 132         return versionInfo.specTitle;
 133     }
 134 
 135     /**
 136      * Returns the version number of the specification
 137      * that this package implements.
 138      * This version string must be a sequence of non-negative decimal
 139      * integers separated by "."'s and may have leading zeros.
 140      * When version strings are compared the most significant
 141      * numbers are compared.
 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.
 169      */
 170     public String getSpecificationVersion() {
 171         return versionInfo.specVersion;
 172     }
 173 
 174     /**
 175      * Return the name of the organization, vendor,
 176      * or company that owns and maintains the specification
 177      * of the classes that implement this package.
 178      * @return the specification vendor, {@code null} is returned if it is not known.
 179      */
 180     public String getSpecificationVendor() {
 181         return versionInfo.specVendor;
 182     }
 183 
 184     /**
 185      * Return the title of this package.
 186      * @return the title of the implementation, {@code null} is returned if it is not known.
 187      */
 188     public String getImplementationTitle() {
 189         return versionInfo.implTitle;
 190     }
 191 
 192     /**
 193      * Return the version of this implementation. It consists of any string
 194      * assigned by the vendor of this implementation and does
 195      * not have any particular syntax specified or expected by the Java
 196      * runtime. It may be compared for equality with other
 197      * package version strings used for this implementation
 198      * by this vendor for this package.
 199      * @return the version of the implementation, {@code null} is returned if it is not known.
 200      */
 201     public String getImplementationVersion() {
 202         return versionInfo.implVersion;
 203     }
 204 
 205     /**
 206      * Returns the vendor that implemented this package, {@code null}
 207      * is returned if it is not known.
 208      * @return the vendor that implemented this package, {@code null}
 209      * is returned if it is not known.
 210      */
 211     public String getImplementationVendor() {
 212         return versionInfo.implVendor;
 213     }
 214 
 215     /**
 216      * Returns true if this package is sealed.
 217      *
 218      * @return true if the package is sealed, false otherwise
 219      */
 220     public boolean isSealed() {
 221         return module().isNamed() || versionInfo.sealBase != null;
 222     }
 223 
 224     /**
 225      * Returns true if this package is sealed with respect to the specified
 226      * code source {@code url}.
 227      *
 228      * @param url the code source URL
 229      * @return true if this package is sealed with respect to the given {@code url}
 230      */
 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         }
 244         return url.equals(sealBase);
 245     }
 246 
 247     /**
 248      * Compare this package's specification version with a
 249      * desired version. It returns true if
 250      * this packages specification version number is greater than or equal
 251      * to the desired version number. <p>
 252      *
 253      * Version numbers are compared by sequentially comparing corresponding
 254      * components of the desired and specification strings.
 255      * Each component is converted as a decimal integer and the values
 256      * compared.
 257      * If the specification value is greater than the desired
 258      * value true is returned. If the value is less false is returned.
 259      * If the values are equal the period is skipped and the next pair of
 260      * components is compared.
 261      *
 262      * @param desired the version string of the desired version.
 263      * @return true if this package's version number is greater
 264      *          than or equal to the desired version number
 265      *
 266      * @exception NumberFormatException if the current version is not known or
 267      *          the desired or current version is not of the correct dotted form.
 268      */
 269     public boolean isCompatibleWith(String desired)
 270         throws NumberFormatException
 271     {
 272         if (versionInfo.specVersion == null || versionInfo.specVersion.length() < 1) {
 273             throw new NumberFormatException("Empty version string");
 274         }
 275 
 276         String [] sa = versionInfo.specVersion.split("\\.", -1);
 277         int [] si = new int[sa.length];
 278         for (int i = 0; i < sa.length; i++) {
 279             si[i] = Integer.parseInt(sa[i]);
 280             if (si[i] < 0)
 281                 throw NumberFormatException.forInputString("" + si[i]);
 282         }
 283 
 284         String [] da = desired.split("\\.", -1);
 285         int [] di = new int[da.length];
 286         for (int i = 0; i < da.length; i++) {
 287             di[i] = Integer.parseInt(da[i]);
 288             if (di[i] < 0)
 289                 throw NumberFormatException.forInputString("" + di[i]);
 290         }
 291 
 292         int len = Math.max(di.length, si.length);
 293         for (int i = 0; i < len; i++) {
 294             int d = (i < di.length ? di[i] : 0);
 295             int s = (i < si.length ? si[i] : 0);
 296             if (s < d)
 297                 return false;
 298             if (s > d)
 299                 return true;
 300         }
 301         return true;
 302     }
 303 
 304     /**
 305      * Finds a package by name in the caller's class loader and its
 306      * ancestors.
 307      * <p>
 308      * If the caller's class loader defines a {@code Package} of the given name,
 309      * the {@code Package} is returned. Otherwise, the ancestors of the
 310      * caller's class loader are searched recursively (parent by parent)
 311      * for a {@code Package} of the given name.
 312      * <p>
 313      * Calling this method is equivalent to calling {@link ClassLoader#getPackage}
 314      * on a {@code ClassLoader} instance which is the caller's class loader.
 315      *
 316      * @param name A package name, such as "{@code java.lang}".
 317      * @return The {@code Package} of the given name defined by the caller's
 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
 334      */
 335     @CallerSensitive
 336     @Deprecated
 337     @SuppressWarnings("deprecation")
 338     public static Package getPackage(String name) {
 339         ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass());
 340         return l != null ? l.getPackage(name) : BootLoader.getDefinedPackage(name);
 341     }
 342 
 343     /**
 344      * Returns all of the {@code Package}s defined by the caller's class loader
 345      * and its ancestors.  The returned array may contain more than one
 346      * {@code Package} object of the same package name, each defined by
 347      * a different class loader in the class loader hierarchy.
 348      * <p>
 349      * Calling this method is equivalent to calling {@link ClassLoader#getPackages}
 350      * on a {@code ClassLoader} instance which is the caller's class loader.
 351      *
 352      * @return  The array of {@code Package} objects defined by this
 353      *          class loader and its ancestors
 354      *
 355      * @see ClassLoader#getDefinedPackages
 356      */
 357     @CallerSensitive
 358     public static Package[] getPackages() {
 359         ClassLoader cl = ClassLoader.getClassLoader(Reflection.getCallerClass());
 360         return cl != null ? cl.getPackages() : BootLoader.packages().toArray(Package[]::new);
 361     }
 362 
 363     /**
 364      * Return the hash code computed from the package name.
 365      * @return the hash code computed from the package name.
 366      */
 367     @Override
 368     public int hashCode(){
 369         return packageName().hashCode();
 370     }
 371 
 372     /**
 373      * Returns the string representation of this Package.
 374      * Its value is the string "package " and the package name.
 375      * If the package title is defined it is appended.
 376      * If the package version is defined it is appended.
 377      * @return the string representation of the package.
 378      */
 379     @Override
 380     public String toString() {
 381         String spec = versionInfo.specTitle;
 382         String ver =  versionInfo.specVersion;
 383         if (spec != null && spec.length() > 0)
 384             spec = ", " + spec;
 385         else
 386             spec = "";
 387         if (ver != null && ver.length() > 0)
 388             ver = ", version " + ver;
 389         else
 390             ver = "";
 391         return "package " + packageName() + spec + ver;
 392     }
 393 
 394     private Class<?> getPackageInfo() {
 395         if (packageInfo == null) {
 396             // find package-info.class defined by loader
 397             String cn = packageName() + ".package-info";
 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 {
 405                 // store a proxy for the package info that has no annotations
 406                 class PackageInfoProxy {}
 407                 packageInfo = PackageInfoProxy.class;
 408             }
 409         }
 410         return packageInfo;
 411     }
 412 
 413     /**
 414      * @throws NullPointerException {@inheritDoc}
 415      * @since 1.5
 416      */
 417     public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
 418         return getPackageInfo().getAnnotation(annotationClass);
 419     }
 420 
 421     /**
 422      * {@inheritDoc}
 423      * @throws NullPointerException {@inheritDoc}
 424      * @since 1.5
 425      */
 426     @Override
 427     public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
 428         return AnnotatedElement.super.isAnnotationPresent(annotationClass);
 429     }
 430 
 431     /**
 432      * @throws NullPointerException {@inheritDoc}
 433      * @since 1.8
 434      */
 435     @Override
 436     public  <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass) {
 437         return getPackageInfo().getAnnotationsByType(annotationClass);
 438     }
 439 
 440     /**
 441      * @since 1.5
 442      */
 443     public Annotation[] getAnnotations() {
 444         return getPackageInfo().getAnnotations();
 445     }
 446 
 447     /**
 448      * @throws NullPointerException {@inheritDoc}
 449      * @since 1.8
 450      */
 451     @Override
 452     public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
 453         return getPackageInfo().getDeclaredAnnotation(annotationClass);
 454     }
 455 
 456     /**
 457      * @throws NullPointerException {@inheritDoc}
 458      * @since 1.8
 459      */
 460     @Override
 461     public <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A> annotationClass) {
 462         return getPackageInfo().getDeclaredAnnotationsByType(annotationClass);
 463     }
 464 
 465     /**
 466      * @since 1.5
 467      */
 468     public Annotation[] getDeclaredAnnotations()  {
 469         return getPackageInfo().getDeclaredAnnotations();
 470     }
 471 
 472     /**
 473      * Construct a package instance for an unnamed module
 474      * with the specified version information.
 475      *
 476      * @apiNote
 477      * This method should not be called to define a Package for named module.
 478      *
 479      * @param name the name of the package
 480      * @param spectitle the title of the specification
 481      * @param specversion the version of the specification
 482      * @param specvendor the organization that maintains the specification
 483      * @param impltitle the title of the implementation
 484      * @param implversion the version of 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
 488      */
 489     Package(String name,
 490             String spectitle, String specversion, String specvendor,
 491             String impltitle, String implversion, String implvendor,
 492             URL sealbase, ClassLoader loader)
 493     {
 494         super(Objects.requireNonNull(name),
 495               loader != null ? loader.getUnnamedModule()
 496                              : BootLoader.getUnnamedModule());
 497 
 498         this.versionInfo = VersionInfo.getInstance(spectitle, specversion,
 499                                                    specvendor, impltitle,
 500                                                    implversion, implvendor,
 501                                                    sealbase);
 502     }
 503 
 504     Package(String name, Module module) {
 505         super(name, module);
 506         this.versionInfo = VersionInfo.NULL_VERSION_INFO;
 507     }
 508 
 509     /*
 510      * Versioning information.  Only for packages in unnamed modules.
 511      */
 512     static class VersionInfo {
 513         static final VersionInfo NULL_VERSION_INFO
 514             = new VersionInfo(null, null, null, null, null, null, null);
 515 
 516         private final String specTitle;
 517         private final String specVersion;
 518         private final String specVendor;
 519         private final String implTitle;
 520         private final String implVersion;
 521         private final String implVendor;
 522         private final URL sealBase;
 523 
 524         static VersionInfo getInstance(String spectitle, String specversion,
 525                                        String specvendor, String impltitle,
 526                                        String implversion, String implvendor,
 527                                        URL sealbase) {
 528             if (spectitle == null && specversion == null &&
 529                     specvendor == null && impltitle == null &&
 530                     implvendor == null && sealbase == null) {
 531                 return NULL_VERSION_INFO;
 532             }
 533             return new VersionInfo(spectitle, specversion, specvendor,
 534                     impltitle, implversion, implvendor,
 535                     sealbase);
 536         }
 537 
 538         private VersionInfo(String spectitle, String specversion,
 539                             String specvendor, String impltitle,
 540                             String implversion, String implvendor,
 541                             URL sealbase)
 542         {
 543             this.implTitle = impltitle;
 544             this.implVersion = implversion;
 545             this.implVendor = implvendor;
 546             this.specTitle = spectitle;
 547             this.specVersion = specversion;
 548             this.specVendor = specvendor;
 549             this.sealBase = sealbase;
 550         }
 551     }
 552 
 553     private final VersionInfo versionInfo;
 554     private Class<?> packageInfo;
 555 }