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.reflect.AnnotatedElement;
29 import java.io.InputStream;
30 import java.util.Enumeration;
31
32 import java.util.StringTokenizer;
33 import java.io.File;
34 import java.io.FileInputStream;
35 import java.io.FileNotFoundException;
36 import java.io.IOException;
37 import java.net.URL;
38 import java.net.MalformedURLException;
39 import java.security.AccessController;
40 import java.security.PrivilegedAction;
41
42 import java.util.jar.JarInputStream;
43 import java.util.jar.Manifest;
44 import java.util.jar.Attributes;
45 import java.util.jar.Attributes.Name;
46 import java.util.jar.JarException;
47 import java.util.Map;
48 import java.util.HashMap;
49 import java.util.Iterator;
50
51 import sun.net.www.ParseUtil;
52 import sun.reflect.CallerSensitive;
53 import sun.reflect.Reflection;
54
55 import java.lang.annotation.Annotation;
56
57 /**
58 * {@code Package} objects contain version information
59 * about the implementation and specification of a Java package.
60 * This versioning information is retrieved and made available
61 * by the {@link ClassLoader} instance that
62 * loaded the class(es). Typically, it is stored in the manifest that is
63 * distributed with the classes.
64 *
65 * <p>The set of classes that make up the package may implement a
66 * particular specification and if so the specification title, version number,
67 * and vendor strings identify that specification.
68 * An application can ask if the package is
69 * compatible with a particular version, see the {@link
521 }
522 }
523 if ("true".equalsIgnoreCase(sealed)) {
524 sealBase = url;
525 }
526 pkgName = name;
527 this.specTitle = specTitle;
528 this.specVersion = specVersion;
529 this.specVendor = specVendor;
530 this.implTitle = implTitle;
531 this.implVersion = implVersion;
532 this.implVendor = implVendor;
533 this.sealBase = sealBase;
534 this.loader = loader;
535 }
536
537 /*
538 * Returns the loaded system package for the specified name.
539 */
540 static Package getSystemPackage(String name) {
541 synchronized (pkgs) {
542 Package pkg = pkgs.get(name);
543 if (pkg == null) {
544 name = name.replace('.', '/').concat("/");
545 String fn = getSystemPackage0(name);
546 if (fn != null) {
547 pkg = defineSystemPackage(name, fn);
548 }
549 }
550 return pkg;
551 }
552 }
553
554 /*
555 * Return an array of loaded system packages.
556 */
557 static Package[] getSystemPackages() {
558 // First, update the system package map with new package names
559 String[] names = getSystemPackages0();
560 synchronized (pkgs) {
561 for (String name : names) {
562 defineSystemPackage(name, getSystemPackage0(name));
563 }
564 return pkgs.values().toArray(new Package[pkgs.size()]);
565 }
566 }
567
568 private static Package defineSystemPackage(final String iname,
569 final String fn)
570 {
571 return AccessController.doPrivileged(new PrivilegedAction<Package>() {
572 public Package run() {
573 String name = iname;
574 // Get the cached code source url for the file name
575 URL url = urls.get(fn);
576 if (url == null) {
577 // URL not found, so create one
578 File file = new File(fn);
579 try {
580 url = ParseUtil.fileToEncodedURL(file);
581 } catch (MalformedURLException e) {
582 }
583 if (url != null) {
584 urls.put(fn, url);
585 // If loading a JAR file, then also cache the manifest
586 if (file.isFile()) {
587 mans.put(fn, loadManifest(fn));
588 }
589 }
590 }
591 // Convert to "."-separated package name
592 name = name.substring(0, name.length() - 1).replace('/', '.');
593 Package pkg;
594 Manifest man = mans.get(fn);
595 if (man != null) {
596 pkg = new Package(name, man, url, null);
597 } else {
598 pkg = new Package(name, null, null, null,
599 null, null, null, null, null);
600 }
601 pkgs.put(name, pkg);
602 return pkg;
603 }
604 });
605 }
606
607 /*
608 * Returns the Manifest for the specified JAR file name.
609 */
610 private static Manifest loadManifest(String fn) {
611 try (FileInputStream fis = new FileInputStream(fn);
612 JarInputStream jis = new JarInputStream(fis, false))
613 {
614 return jis.getManifest();
615 } catch (IOException e) {
616 return null;
617 }
618 }
619
620 // The map of loaded system packages
621 private static Map<String, Package> pkgs = new HashMap<>(31);
622
623 // Maps each directory or zip file name to its corresponding url
624 private static Map<String, URL> urls = new HashMap<>(10);
625
626 // Maps each code source url for a jar file to its manifest
627 private static Map<String, Manifest> mans = new HashMap<>(10);
628
629 private static native String getSystemPackage0(String name);
630 private static native String[] getSystemPackages0();
631
632 /*
633 * Private storage for the package name and attributes.
634 */
635 private final String pkgName;
636 private final String specTitle;
637 private final String specVersion;
638 private final String specVendor;
639 private final String implTitle;
640 private final String implVersion;
641 private final String implVendor;
642 private final URL sealBase;
643 private transient final ClassLoader loader;
644 private transient Class<?> packageInfo;
645 }
|
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.reflect.AnnotatedElement;
29
30 import java.io.File;
31 import java.io.FileInputStream;
32 import java.io.IOException;
33 import java.net.URL;
34 import java.net.MalformedURLException;
35 import java.security.AccessController;
36 import java.security.PrivilegedAction;
37
38 import java.util.concurrent.ConcurrentHashMap;
39 import java.util.jar.JarInputStream;
40 import java.util.jar.Manifest;
41 import java.util.jar.Attributes;
42 import java.util.jar.Attributes.Name;
43 import java.util.Map;
44
45 import sun.net.www.ParseUtil;
46 import sun.reflect.CallerSensitive;
47 import sun.reflect.Reflection;
48
49 import java.lang.annotation.Annotation;
50
51 /**
52 * {@code Package} objects contain version information
53 * about the implementation and specification of a Java package.
54 * This versioning information is retrieved and made available
55 * by the {@link ClassLoader} instance that
56 * loaded the class(es). Typically, it is stored in the manifest that is
57 * distributed with the classes.
58 *
59 * <p>The set of classes that make up the package may implement a
60 * particular specification and if so the specification title, version number,
61 * and vendor strings identify that specification.
62 * An application can ask if the package is
63 * compatible with a particular version, see the {@link
515 }
516 }
517 if ("true".equalsIgnoreCase(sealed)) {
518 sealBase = url;
519 }
520 pkgName = name;
521 this.specTitle = specTitle;
522 this.specVersion = specVersion;
523 this.specVendor = specVendor;
524 this.implTitle = implTitle;
525 this.implVersion = implVersion;
526 this.implVendor = implVendor;
527 this.sealBase = sealBase;
528 this.loader = loader;
529 }
530
531 /*
532 * Returns the loaded system package for the specified name.
533 */
534 static Package getSystemPackage(String name) {
535 Package pkg = pkgs.get(name);
536 if (pkg == null) {
537 name = name.replace('.', '/').concat("/");
538 String fn = getSystemPackage0(name);
539 if (fn != null) {
540 pkg = defineSystemPackage(name, fn);
541 }
542 }
543 return pkg;
544 }
545
546 /*
547 * Return an array of loaded system packages.
548 */
549 static Package[] getSystemPackages() {
550 // First, update the system package map with new package names
551 String[] names = getSystemPackages0();
552 for (String name : names) {
553 if (!pkgs.containsKey(name)) {
554 defineSystemPackage(name, getSystemPackage0(name));
555 }
556 }
557 return pkgs.values().toArray(new Package[pkgs.size()]);
558 }
559
560 private static Package defineSystemPackage(final String iname,
561 final String fn)
562 {
563 // Convert to "."-separated package name
564 String name = iname.substring(0, iname.length() - 1).replace('/', '.');
565 // Creates a cached manifest for the file name, allowing
566 // only-once, lazy reads of manifest from jar files
567 CachedManifest cachedManifest = createCachedManifest(fn);
568 pkgs.putIfAbsent(name, new Package(name, cachedManifest.getManifest(),
569 cachedManifest.getURL(), null));
570 // Ensure we only expose one Package object
571 return pkgs.get(name);
572 }
573
574 private static CachedManifest createCachedManifest(String fn) {
575 if (!manifests.containsKey(fn)) {
576 manifests.putIfAbsent(fn, new CachedManifest(fn));
577 }
578 return manifests.get(fn);
579 }
580
581 // The map of loaded system packages
582 private static final ConcurrentHashMap<String, Package> pkgs
583 = new ConcurrentHashMap<>();
584
585 // Maps each directory or zip file name to its corresponding manifest, if
586 // it exists
587 private static final ConcurrentHashMap<String, CachedManifest> manifests
588 = new ConcurrentHashMap<>();
589
590 private static class CachedManifest {
591 private static final Manifest EMPTY_MANIFEST = new Manifest();
592 private final String fileName;
593 private final URL url;
594 private volatile Manifest manifest;
595
596 CachedManifest(final String fileName) {
597 this.fileName = fileName;
598 this.url = AccessController.doPrivileged(new PrivilegedAction<URL>() {
599 public URL run() {
600 final File file = new File(fileName);
601 if (file.isFile()) {
602 try {
603 return ParseUtil.fileToEncodedURL(file);
604 } catch (MalformedURLException e) {
605 }
606 }
607 return null;
608 }
609 });
610 }
611
612 public URL getURL() {
613 return url;
614 }
615
616 public Manifest getManifest() {
617 if (url == null) {
618 return EMPTY_MANIFEST;
619 }
620 Manifest m = manifest;
621 if (m != null) {
622 return m;
623 }
624 synchronized (this) {
625 m = manifest;
626 if (m != null) {
627 return m;
628 }
629 m = AccessController.doPrivileged(new PrivilegedAction<Manifest>() {
630 public Manifest run() {
631 try (FileInputStream fis = new FileInputStream(fileName);
632 JarInputStream jis = new JarInputStream(fis, false)) {
633 return jis.getManifest();
634 } catch (IOException e) {
635 return null;
636 }
637 }
638 });
639 manifest = m = (m == null ? EMPTY_MANIFEST : m);
640 }
641 return m;
642 }
643 }
644
645 private static native String getSystemPackage0(String name);
646 private static native String[] getSystemPackages0();
647
648 /*
649 * Private storage for the package name and attributes.
650 */
651 private final String pkgName;
652 private final String specTitle;
653 private final String specVersion;
654 private final String specVendor;
655 private final String implTitle;
656 private final String implVersion;
657 private final String implVendor;
658 private final URL sealBase;
659 private transient final ClassLoader loader;
660 private transient Class<?> packageInfo;
661 }
|