Package.java revision 16177:89ef4b822745
1178786Skmacy/*
2178786Skmacy * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
3178786Skmacy * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4178786Skmacy *
5178786Skmacy * This code is free software; you can redistribute it and/or modify it
6178786Skmacy * under the terms of the GNU General Public License version 2 only, as
7178786Skmacy * published by the Free Software Foundation.  Oracle designates this
8178786Skmacy * particular file as subject to the "Classpath" exception as provided
9178786Skmacy * by Oracle in the LICENSE file that accompanied this code.
10178786Skmacy *
11178786Skmacy * This code is distributed in the hope that it will be useful, but WITHOUT
12178786Skmacy * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13178786Skmacy * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14178786Skmacy * version 2 for more details (a copy is included in the LICENSE file that
15178786Skmacy * accompanied this code).
16178786Skmacy *
17178786Skmacy * You should have received a copy of the GNU General Public License version
18178786Skmacy * 2 along with this work; if not, write to the Free Software Foundation,
19178786Skmacy * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20178786Skmacy *
21178786Skmacy * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22178786Skmacy * or visit www.oracle.com if you need additional information or have any
23178786Skmacy * questions.
24178786Skmacy */
25178786Skmacy
26178786Skmacypackage java.lang;
27178786Skmacy
28178786Skmacyimport java.lang.annotation.Annotation;
29178786Skmacyimport java.lang.reflect.AnnotatedElement;
30178786Skmacyimport java.lang.reflect.Module;
31178786Skmacyimport java.net.MalformedURLException;
32178786Skmacyimport java.net.URI;
33178786Skmacyimport java.net.URL;
34178786Skmacyimport java.security.AccessController;
35237263Snpimport java.security.PrivilegedAction;
36237263Snpimport java.util.Objects;
37237263Snp
38178786Skmacyimport jdk.internal.loader.BootLoader;
39178786Skmacyimport jdk.internal.reflect.CallerSensitive;
40178786Skmacyimport jdk.internal.reflect.Reflection;
41178786Skmacy
42178786Skmacy
43178786Skmacy/**
44178786Skmacy * Represents metadata about a run-time package associated with a class loader.
45178786Skmacy * Metadata includes annotations, versioning, and sealing.
46178786Skmacy * <p>
47178786Skmacy * Annotations for the run-time package are read from {@code package-info.class}
48178786Skmacy * at the same code source as classes in the run-time package.
49178786Skmacy * <p>
50178786Skmacy * The set of classes that make up the run-time package may implement a
51178786Skmacy * particular specification. The specification title, version, and vendor
52178786Skmacy * (indicating the owner/maintainer of the specification) can be provided
53178786Skmacy * when the {@code Package} is defined. An application can ask if the
54178786Skmacy * {@code Package} is compatible with a particular specification version
55178786Skmacy * by using the {@link #isCompatibleWith Package.isCompatibleWith(String)}
56178786Skmacy * method. In addition, information about the actual classes that make up the
57178786Skmacy * run-time package can be provided when the Package is defined.
58178786Skmacy * This information consists of an implementation title, version, and vendor
59178786Skmacy * (indicating the supplier of the classes).
60178786Skmacy * <p>
61178786Skmacy * A {@code Package} may be explicitly defined with
62178786Skmacy * the {@link ClassLoader#definePackage(String, String, String, String,
63178786Skmacy * String, String, String, URL)} method.
64178786Skmacy * The caller supplies the specification and implementation titles, versions, and
65178786Skmacy * vendors. The caller also indicates whether the package is
66178786Skmacy * {@linkplain java.util.jar.Attributes.Name#SEALED sealed}.
67178786Skmacy * If a {@code Package} is not explicitly defined for a run-time package when
68178786Skmacy * a class in that run-time package is defined, then a {@code Package} is
69178786Skmacy * automatically defined by the class's defining class loader, as follows.
70178786Skmacy * <p>
71178786Skmacy * A {@code Package} automatically defined for classes in a named module has
72178786Skmacy * the following properties:
73178786Skmacy * <ul>
74178786Skmacy * <li>The name of the package is derived from the {@linkplain Class#getName() binary names}
75178786Skmacy *     of the classes. Since classes in a named module must be in a named package,
76178786Skmacy *     the derived name is never empty.</li>
77178786Skmacy * <li>The package is sealed with the {@linkplain java.lang.module.ModuleReference#location()
78178786Skmacy *     module location} as the code source, if known.</li>
79178786Skmacy * <li>The specification and implementation titles, versions, and vendors
80178786Skmacy *     are unspecified.</li>
81178786Skmacy * <li>Any annotations on the package are read from {@code package-info.class}
82178786Skmacy *     as specified above.</li>
83178786Skmacy * </ul>
84178786Skmacy * <p>
85178786Skmacy * A {@code Package} automatically defined for classes in an unnamed module
86178786Skmacy * has the following properties:
87178786Skmacy * <ul>
88178786Skmacy * <li>The name of the package is either {@code ""} (for classes in an unnamed package)
89178786Skmacy *     or derived from the {@linkplain Class#getName() binary names} of the classes
90178786Skmacy *     (for classes in a named package).</li>
91178786Skmacy * <li>The package is not sealed.</li>
92178786Skmacy * <li>The specification and implementation titles, versions, and vendors
93178786Skmacy *     are unspecified.</li>
94178786Skmacy * <li>Any annotations on the package are read from {@code package-info.class}
95178786Skmacy *     as specified above.</li>
96178786Skmacy * </ul>
97178786Skmacy *
98178786Skmacy * <p>
99178786Skmacy * A {@code Package} can be obtained with the {@link Package#getPackage
100178786Skmacy * Package.getPackage(String)} and {@link ClassLoader#getDefinedPackage
101178786Skmacy * ClassLoader.getDefinedPackage(String)} methods.
102178786Skmacy * Every {@code Package} defined by a class loader can be obtained
103178786Skmacy * with the {@link Package#getPackages Package.getPackages()} and
104178786Skmacy * {@link ClassLoader#getDefinedPackages} methods.
105178786Skmacy *
106178786Skmacy * @jvms 5.3 Run-time package
107178786Skmacy * @see <a href="../../../technotes/guides/jar/jar.html#versioning">
108178786Skmacy * The JAR File Specification: Package Versioning</a>
109178786Skmacy * @see <a href="../../../technotes/guides/jar/jar.html#sealing">
110178786Skmacy * The JAR File Specification: Package Sealing</a>
111178786Skmacy * @see ClassLoader#definePackage(String, String, String, String, String, String, String, URL)
112178786Skmacy *
113178786Skmacy * @since 1.2
114178786Skmacy */
115178786Skmacypublic class Package extends NamedPackage implements java.lang.reflect.AnnotatedElement {
116178786Skmacy    /**
117178786Skmacy     * Return the name of this package.
118178786Skmacy     *
119178786Skmacy     * @return  The fully-qualified name of this package as defined in section 6.5.3 of
120178786Skmacy     *          <cite>The Java&trade; Language Specification</cite>,
121178786Skmacy     *          for example, {@code java.lang}
122178786Skmacy     */
123178786Skmacy    public String getName() {
124178786Skmacy        return packageName();
125178786Skmacy    }
126178786Skmacy
127178786Skmacy    /**
128178786Skmacy     * Return the title of the specification that this package implements.
129178786Skmacy     * @return the specification title, {@code null} is returned if it is not known.
130178786Skmacy     */
131178786Skmacy    public String getSpecificationTitle() {
132178786Skmacy        return versionInfo.specTitle;
133178786Skmacy    }
134178786Skmacy
135178786Skmacy    /**
136178786Skmacy     * Returns the version number of the specification
137178786Skmacy     * that this package implements.
138178786Skmacy     * This version string must be a sequence of non-negative decimal
139178786Skmacy     * integers separated by "."'s and may have leading zeros.
140178786Skmacy     * When version strings are compared the most significant
141178786Skmacy     * numbers are compared.
142178786Skmacy     *
143178786Skmacy     *
144178786Skmacy     * <p>Specification version numbers use a syntax that consists of non-negative
145178786Skmacy     * decimal integers separated by periods ".", for example "2.0" or
146178786Skmacy     * "1.2.3.4.5.6.7".  This allows an extensible number to be used to represent
147178786Skmacy     * major, minor, micro, etc. versions.  The version specification is described
148178786Skmacy     * by the following formal grammar:
149178786Skmacy     * <blockquote>
150178786Skmacy     * <dl>
151178786Skmacy     * <dt><i>SpecificationVersion:</i>
152178786Skmacy     * <dd><i>Digits RefinedVersion<sub>opt</sub></i>
153178786Skmacy
154178786Skmacy     * <dt><i>RefinedVersion:</i>
155178786Skmacy     * <dd>{@code .} <i>Digits</i>
156178786Skmacy     * <dd>{@code .} <i>Digits RefinedVersion</i>
157178786Skmacy     *
158178786Skmacy     * <dt><i>Digits:</i>
159178786Skmacy     * <dd><i>Digit</i>
160178786Skmacy     * <dd><i>Digits</i>
161178786Skmacy     *
162178786Skmacy     * <dt><i>Digit:</i>
163178786Skmacy     * <dd>any character for which {@link Character#isDigit} returns {@code true},
164178786Skmacy     * e.g. 0, 1, 2, ...
165178786Skmacy     * </dl>
166178786Skmacy     * </blockquote>
167178786Skmacy     *
168178786Skmacy     * @return the specification version, {@code null} is returned if it is not known.
169178786Skmacy     */
170178786Skmacy    public String getSpecificationVersion() {
171178786Skmacy        return versionInfo.specVersion;
172178786Skmacy    }
173178786Skmacy
174178786Skmacy    /**
175178786Skmacy     * Return the name of the organization, vendor,
176178786Skmacy     * or company that owns and maintains the specification
177178786Skmacy     * of the classes that implement this package.
178178786Skmacy     * @return the specification vendor, {@code null} is returned if it is not known.
179178786Skmacy     */
180178786Skmacy    public String getSpecificationVendor() {
181178786Skmacy        return versionInfo.specVendor;
182178786Skmacy    }
183178786Skmacy
184178786Skmacy    /**
185178786Skmacy     * Return the title of this package.
186178786Skmacy     * @return the title of the implementation, {@code null} is returned if it is not known.
187178786Skmacy     */
188178786Skmacy    public String getImplementationTitle() {
189178786Skmacy        return versionInfo.implTitle;
190178786Skmacy    }
191178786Skmacy
192178786Skmacy    /**
193178786Skmacy     * Return the version of this implementation. It consists of any string
194178786Skmacy     * assigned by the vendor of this implementation and does
195178786Skmacy     * not have any particular syntax specified or expected by the Java
196178786Skmacy     * runtime. It may be compared for equality with other
197178786Skmacy     * package version strings used for this implementation
198178786Skmacy     * by this vendor for this package.
199178786Skmacy     * @return the version of the implementation, {@code null} is returned if it is not known.
200178786Skmacy     */
201178786Skmacy    public String getImplementationVersion() {
202178786Skmacy        return versionInfo.implVersion;
203178786Skmacy    }
204178786Skmacy
205178786Skmacy    /**
206178786Skmacy     * Returns the vendor that implemented this package, {@code null}
207178786Skmacy     * is returned if it is not known.
208178786Skmacy     * @return the vendor that implemented this package, {@code null}
209178786Skmacy     * is returned if it is not known.
210178786Skmacy     */
211178786Skmacy    public String getImplementationVendor() {
212178786Skmacy        return versionInfo.implVendor;
213178786Skmacy    }
214178786Skmacy
215178786Skmacy    /**
216178786Skmacy     * Returns true if this package is sealed.
217178786Skmacy     *
218178786Skmacy     * @return true if the package is sealed, false otherwise
219178786Skmacy     */
220178786Skmacy    public boolean isSealed() {
221178786Skmacy        return module().isNamed() || versionInfo.sealBase != null;
222178786Skmacy    }
223178786Skmacy
224178786Skmacy    /**
225178786Skmacy     * Returns true if this package is sealed with respect to the specified
226178786Skmacy     * code source {@code url}.
227178786Skmacy     *
228178786Skmacy     * @param url the code source URL
229178786Skmacy     * @return true if this package is sealed with respect to the given {@code url}
230178786Skmacy     */
231178786Skmacy    public boolean isSealed(URL url) {
232178786Skmacy        Objects.requireNonNull(url);
233178786Skmacy
234178786Skmacy        URL sealBase = null;
235178786Skmacy        if (versionInfo != VersionInfo.NULL_VERSION_INFO) {
236178786Skmacy            sealBase = versionInfo.sealBase;
237178786Skmacy        } else {
238178786Skmacy            try {
239178786Skmacy                URI uri = location();
240178786Skmacy                sealBase = uri != null ? uri.toURL() : null;
241178786Skmacy            } catch (MalformedURLException e) {
242178786Skmacy            }
243178786Skmacy        }
244178786Skmacy        return url.equals(sealBase);
245178786Skmacy    }
246178786Skmacy
247178786Skmacy    /**
248178786Skmacy     * Compare this package's specification version with a
249178786Skmacy     * desired version. It returns true if
250178786Skmacy     * this packages specification version number is greater than or equal
251178786Skmacy     * to the desired version number. <p>
252178786Skmacy     *
253178786Skmacy     * Version numbers are compared by sequentially comparing corresponding
254178786Skmacy     * components of the desired and specification strings.
255178786Skmacy     * Each component is converted as a decimal integer and the values
256178786Skmacy     * compared.
257178786Skmacy     * If the specification value is greater than the desired
258178786Skmacy     * value true is returned. If the value is less false is returned.
259178786Skmacy     * If the values are equal the period is skipped and the next pair of
260178786Skmacy     * components is compared.
261178786Skmacy     *
262178786Skmacy     * @param desired the version string of the desired version.
263178786Skmacy     * @return true if this package's version number is greater
264178786Skmacy     *          than or equal to the desired version number
265178786Skmacy     *
266178786Skmacy     * @exception NumberFormatException if the current version is not known or
267178786Skmacy     *          the desired or current version is not of the correct dotted form.
268178786Skmacy     */
269178786Skmacy    public boolean isCompatibleWith(String desired)
270178786Skmacy        throws NumberFormatException
271178786Skmacy    {
272178786Skmacy        if (versionInfo.specVersion == null || versionInfo.specVersion.length() < 1) {
273178786Skmacy            throw new NumberFormatException("Empty version string");
274178786Skmacy        }
275178786Skmacy
276178786Skmacy        String [] sa = versionInfo.specVersion.split("\\.", -1);
277178786Skmacy        int [] si = new int[sa.length];
278237263Snp        for (int i = 0; i < sa.length; i++) {
279237263Snp            si[i] = Integer.parseInt(sa[i]);
280237263Snp            if (si[i] < 0)
281237263Snp                throw NumberFormatException.forInputString("" + si[i]);
282237263Snp        }
283237263Snp
284237263Snp        String [] da = desired.split("\\.", -1);
285237263Snp        int [] di = new int[da.length];
286237263Snp        for (int i = 0; i < da.length; i++) {
287237263Snp            di[i] = Integer.parseInt(da[i]);
288237263Snp            if (di[i] < 0)
289237263Snp                throw NumberFormatException.forInputString("" + di[i]);
290237263Snp        }
291237263Snp
292237263Snp        int len = Math.max(di.length, si.length);
293237263Snp        for (int i = 0; i < len; i++) {
294178786Skmacy            int d = (i < di.length ? di[i] : 0);
295178786Skmacy            int s = (i < si.length ? si[i] : 0);
296178786Skmacy            if (s < d)
297178786Skmacy                return false;
298178786Skmacy            if (s > d)
299178786Skmacy                return true;
300178786Skmacy        }
301178786Skmacy        return true;
302178786Skmacy    }
303178786Skmacy
304178786Skmacy    /**
305178786Skmacy     * Finds a package by name in the caller's class loader and its
306178786Skmacy     * ancestors.
307178786Skmacy     * <p>
308178786Skmacy     * If the caller's class loader defines a {@code Package} of the given name,
309237263Snp     * the {@code Package} is returned. Otherwise, the ancestors of the
310237263Snp     * caller's class loader are searched recursively (parent by parent)
311237263Snp     * for a {@code Package} of the given name.
312178786Skmacy     * <p>
313237263Snp     * Calling this method is equivalent to calling {@link ClassLoader#getPackage}
314178786Skmacy     * on a {@code ClassLoader} instance which is the caller's class loader.
315178786Skmacy     *
316178786Skmacy     * @param name A package name, such as "{@code java.lang}".
317178786Skmacy     * @return The {@code Package} of the given name defined by the caller's
318178786Skmacy     *         class loader or its ancestors, or {@code null} if not found.
319178786Skmacy     *
320178786Skmacy     * @throws NullPointerException
321178786Skmacy     *         if {@code name} is {@code null}.
322178786Skmacy     *
323178786Skmacy     * @deprecated
324178786Skmacy     * If multiple class loaders delegate to each other and define classes
325178786Skmacy     * with the same package name, and one such loader relies on the lookup
326178786Skmacy     * behavior of {@code getPackage} to return a {@code Package} from
327178786Skmacy     * a parent loader, then the properties exposed by the {@code Package}
328237263Snp     * may not be as expected in the rest of the program.
329237263Snp     * For example, the {@code Package} will only expose annotations from the
330178786Skmacy     * {@code package-info.class} file defined by the parent loader, even if
331178786Skmacy     * annotations exist in a {@code package-info.class} file defined by
332178786Skmacy     * a child loader.  A more robust approach is to use the
333178786Skmacy     * {@link ClassLoader#getDefinedPackage} method which returns
334237263Snp     * a {@code Package} for the specified class loader.
335178786Skmacy     *
336178786Skmacy     * @see ClassLoader#getDefinedPackage
337178786Skmacy     */
338178786Skmacy    @CallerSensitive
339178786Skmacy    @Deprecated(since="9")
340178786Skmacy    @SuppressWarnings("deprecation")
341178786Skmacy    public static Package getPackage(String name) {
342178786Skmacy        ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass());
343237263Snp        return l != null ? l.getPackage(name) : BootLoader.getDefinedPackage(name);
344237263Snp    }
345178786Skmacy
346178786Skmacy    /**
347178786Skmacy     * Returns all of the {@code Package}s defined by the caller's class loader
348178786Skmacy     * and its ancestors.  The returned array may contain more than one
349178786Skmacy     * {@code Package} object of the same package name, each defined by
350178786Skmacy     * a different class loader in the class loader hierarchy.
351178786Skmacy     * <p>
352178786Skmacy     * Calling this method is equivalent to calling {@link ClassLoader#getPackages}
353178786Skmacy     * on a {@code ClassLoader} instance which is the caller's class loader.
354178786Skmacy     *
355178786Skmacy     * @return  The array of {@code Package} objects defined by this
356178786Skmacy     *          class loader and its ancestors
357178786Skmacy     *
358178786Skmacy     * @see ClassLoader#getDefinedPackages
359178786Skmacy     */
360178786Skmacy    @CallerSensitive
361178786Skmacy    public static Package[] getPackages() {
362178786Skmacy        ClassLoader cl = ClassLoader.getClassLoader(Reflection.getCallerClass());
363178786Skmacy        return cl != null ? cl.getPackages() : BootLoader.packages().toArray(Package[]::new);
364178786Skmacy    }
365178786Skmacy
366178786Skmacy    /**
367178786Skmacy     * Return the hash code computed from the package name.
368178786Skmacy     * @return the hash code computed from the package name.
369178786Skmacy     */
370178786Skmacy    @Override
371178786Skmacy    public int hashCode(){
372178786Skmacy        return packageName().hashCode();
373178786Skmacy    }
374178786Skmacy
375178786Skmacy    /**
376178786Skmacy     * Returns the string representation of this Package.
377178786Skmacy     * Its value is the string "package " and the package name.
378178786Skmacy     * If the package title is defined it is appended.
379178786Skmacy     * If the package version is defined it is appended.
380178786Skmacy     * @return the string representation of the package.
381178786Skmacy     */
382178786Skmacy    @Override
383178786Skmacy    public String toString() {
384178786Skmacy        String spec = versionInfo.specTitle;
385178786Skmacy        String ver =  versionInfo.specVersion;
386178786Skmacy        if (spec != null && spec.length() > 0)
387178786Skmacy            spec = ", " + spec;
388178786Skmacy        else
389178786Skmacy            spec = "";
390178786Skmacy        if (ver != null && ver.length() > 0)
391178786Skmacy            ver = ", version " + ver;
392178786Skmacy        else
393178786Skmacy            ver = "";
394178786Skmacy        return "package " + packageName() + spec + ver;
395178786Skmacy    }
396178786Skmacy
397178786Skmacy    private Class<?> getPackageInfo() {
398178786Skmacy        if (packageInfo == null) {
399178786Skmacy            // find package-info.class defined by loader
400178786Skmacy            String cn = packageName() + ".package-info";
401178786Skmacy            Module module = module();
402178786Skmacy            PrivilegedAction<ClassLoader> pa = module::getClassLoader;
403178786Skmacy            ClassLoader loader = AccessController.doPrivileged(pa);
404178786Skmacy            Class<?> c;
405178786Skmacy            if (loader != null) {
406178786Skmacy                c = loader.loadClass(module, cn);
407178786Skmacy            } else {
408178786Skmacy                c = BootLoader.loadClass(module, cn);
409178786Skmacy            }
410178786Skmacy
411178786Skmacy            if (c != null) {
412178786Skmacy                packageInfo = c;
413178786Skmacy            } else {
414178786Skmacy                // store a proxy for the package info that has no annotations
415178786Skmacy                class PackageInfoProxy {}
416178786Skmacy                packageInfo = PackageInfoProxy.class;
417178786Skmacy            }
418178786Skmacy        }
419178786Skmacy        return packageInfo;
420178786Skmacy    }
421178786Skmacy
422178786Skmacy    /**
423178786Skmacy     * @throws NullPointerException {@inheritDoc}
424178786Skmacy     * @since 1.5
425178786Skmacy     */
426178786Skmacy    public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
427178786Skmacy        return getPackageInfo().getAnnotation(annotationClass);
428178786Skmacy    }
429178786Skmacy
430178786Skmacy    /**
431178786Skmacy     * {@inheritDoc}
432178786Skmacy     * @throws NullPointerException {@inheritDoc}
433178786Skmacy     * @since 1.5
434178786Skmacy     */
435178786Skmacy    @Override
436178786Skmacy    public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
437178786Skmacy        return AnnotatedElement.super.isAnnotationPresent(annotationClass);
438178786Skmacy    }
439178786Skmacy
440178786Skmacy    /**
441178786Skmacy     * @throws NullPointerException {@inheritDoc}
442178786Skmacy     * @since 1.8
443178786Skmacy     */
444178786Skmacy    @Override
445178786Skmacy    public  <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass) {
446178786Skmacy        return getPackageInfo().getAnnotationsByType(annotationClass);
447178786Skmacy    }
448178786Skmacy
449178786Skmacy    /**
450178786Skmacy     * @since 1.5
451178786Skmacy     */
452178786Skmacy    public Annotation[] getAnnotations() {
453178786Skmacy        return getPackageInfo().getAnnotations();
454178786Skmacy    }
455178786Skmacy
456178786Skmacy    /**
457178786Skmacy     * @throws NullPointerException {@inheritDoc}
458178786Skmacy     * @since 1.8
459178786Skmacy     */
460178786Skmacy    @Override
461178786Skmacy    public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
462178786Skmacy        return getPackageInfo().getDeclaredAnnotation(annotationClass);
463178786Skmacy    }
464178786Skmacy
465178786Skmacy    /**
466178786Skmacy     * @throws NullPointerException {@inheritDoc}
467178786Skmacy     * @since 1.8
468178786Skmacy     */
469178786Skmacy    @Override
470178786Skmacy    public <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A> annotationClass) {
471178786Skmacy        return getPackageInfo().getDeclaredAnnotationsByType(annotationClass);
472178786Skmacy    }
473178786Skmacy
474178786Skmacy    /**
475178786Skmacy     * @since 1.5
476178786Skmacy     */
477178786Skmacy    public Annotation[] getDeclaredAnnotations()  {
478178786Skmacy        return getPackageInfo().getDeclaredAnnotations();
479178786Skmacy    }
480178786Skmacy
481178786Skmacy    /**
482178786Skmacy     * Construct a package instance for an unnamed module
483178786Skmacy     * with the specified version information.
484178786Skmacy     *
485178786Skmacy     * @apiNote
486178786Skmacy     * This method should not be called to define a Package for named module.
487178786Skmacy     *
488178786Skmacy     * @param name the name of the package
489178786Skmacy     * @param spectitle the title of the specification
490178786Skmacy     * @param specversion the version of the specification
491178786Skmacy     * @param specvendor the organization that maintains the specification
492178786Skmacy     * @param impltitle the title of the implementation
493178786Skmacy     * @param implversion the version of the implementation
494178786Skmacy     * @param implvendor the organization that maintains the implementation
495178786Skmacy     * @param sealbase code source where this Package comes from
496178786Skmacy     * @param loader defining class loader
497178786Skmacy     */
498178786Skmacy    Package(String name,
499178786Skmacy            String spectitle, String specversion, String specvendor,
500178786Skmacy            String impltitle, String implversion, String implvendor,
501178786Skmacy            URL sealbase, ClassLoader loader)
502178786Skmacy    {
503178786Skmacy        super(Objects.requireNonNull(name),
504178786Skmacy              loader != null ? loader.getUnnamedModule()
505178786Skmacy                             : BootLoader.getUnnamedModule());
506178786Skmacy
507178786Skmacy        this.versionInfo = VersionInfo.getInstance(spectitle, specversion,
508178786Skmacy                                                   specvendor, impltitle,
509178786Skmacy                                                   implversion, implvendor,
510178786Skmacy                                                   sealbase);
511178786Skmacy    }
512178786Skmacy
513178786Skmacy    Package(String name, Module module) {
514178786Skmacy        super(name, module);
515178786Skmacy        this.versionInfo = VersionInfo.NULL_VERSION_INFO;
516178786Skmacy    }
517178786Skmacy
518178786Skmacy    /*
519178786Skmacy     * Versioning information.  Only for packages in unnamed modules.
520178786Skmacy     */
521178786Skmacy    static class VersionInfo {
522178786Skmacy        static final VersionInfo NULL_VERSION_INFO
523178786Skmacy            = new VersionInfo(null, null, null, null, null, null, null);
524178786Skmacy
525178786Skmacy        private final String specTitle;
526178786Skmacy        private final String specVersion;
527178786Skmacy        private final String specVendor;
528178786Skmacy        private final String implTitle;
529178786Skmacy        private final String implVersion;
530178786Skmacy        private final String implVendor;
531178786Skmacy        private final URL sealBase;
532178786Skmacy
533178786Skmacy        static VersionInfo getInstance(String spectitle, String specversion,
534178786Skmacy                                       String specvendor, String impltitle,
535178786Skmacy                                       String implversion, String implvendor,
536178786Skmacy                                       URL sealbase) {
537178786Skmacy            if (spectitle == null && specversion == null &&
538178786Skmacy                    specvendor == null && impltitle == null &&
539178786Skmacy                    implvendor == null && sealbase == null) {
540178786Skmacy                return NULL_VERSION_INFO;
541178786Skmacy            }
542178786Skmacy            return new VersionInfo(spectitle, specversion, specvendor,
543178786Skmacy                    impltitle, implversion, implvendor,
544178786Skmacy                    sealbase);
545178786Skmacy        }
546178786Skmacy
547178786Skmacy        private VersionInfo(String spectitle, String specversion,
548178786Skmacy                            String specvendor, String impltitle,
549178786Skmacy                            String implversion, String implvendor,
550178786Skmacy                            URL sealbase)
551178786Skmacy        {
552178786Skmacy            this.implTitle = impltitle;
553178786Skmacy            this.implVersion = implversion;
554178786Skmacy            this.implVendor = implvendor;
555178786Skmacy            this.specTitle = spectitle;
556178786Skmacy            this.specVersion = specversion;
557237263Snp            this.specVendor = specvendor;
558237263Snp            this.sealBase = sealbase;
559237263Snp        }
560237263Snp    }
561237263Snp
562237263Snp    private final VersionInfo versionInfo;
563178786Skmacy    private Class<?> packageInfo;
564178786Skmacy}
565178786Skmacy