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™ 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 }