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.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]);
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]);
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 }
580