567 return findClassOnClassPathOrNull(cn);
568 }
569
570 return null;
571 }
572
573 /**
574 * Loads the class with the specified binary name.
575 */
576 @Override
577 protected Class<?> loadClass(String cn, boolean resolve)
578 throws ClassNotFoundException
579 {
580 Class<?> c = loadClassOrNull(cn, resolve);
581 if (c == null)
582 throw new ClassNotFoundException(cn);
583 return c;
584 }
585
586 /**
587 * A variation of {@code loadCass} to load a class with the specified
588 * binary name. This method returns {@code null} when the class is not
589 * found.
590 */
591 protected Class<?> loadClassOrNull(String cn, boolean resolve) {
592 synchronized (getClassLoadingLock(cn)) {
593 // check if already loaded
594 Class<?> c = findLoadedClass(cn);
595
596 if (c == null) {
597
598 // find the candidate module for this class
599 LoadedModule loadedModule = findLoadedModule(cn);
600 if (loadedModule != null) {
601
602 // package is in a module
603 BuiltinClassLoader loader = loadedModule.loader();
604 if (loader == this) {
605 if (VM.isModuleSystemInited()) {
606 c = findClassInModuleOrNull(loadedModule, cn);
607 }
616 if (parent != null) {
617 c = parent.loadClassOrNull(cn);
618 }
619
620 // check class path
621 if (c == null && hasClassPath() && VM.isModuleSystemInited()) {
622 c = findClassOnClassPathOrNull(cn);
623 }
624 }
625
626 }
627
628 if (resolve && c != null)
629 resolveClass(c);
630
631 return c;
632 }
633 }
634
635 /**
636 * A variation of {@code loadCass} to load a class with the specified
637 * binary name. This method returns {@code null} when the class is not
638 * found.
639 */
640 protected Class<?> loadClassOrNull(String cn) {
641 return loadClassOrNull(cn, false);
642 }
643
644 /**
645 * Find the candidate loaded module for the given class name.
646 * Returns {@code null} if none of the modules defined to this
647 * class loader contain the API package for the class.
648 */
649 private LoadedModule findLoadedModule(String cn) {
650 int pos = cn.lastIndexOf('.');
651 if (pos < 0)
652 return null; // unnamed package
653
654 String pn = cn.substring(0, pos);
655 return packageToModule.get(pn);
656 }
657
658 /**
659 * Find the candidate loaded module for the given class name
660 * in the named module. Returns {@code null} if the named module
661 * is not defined to this class loader or does not contain
662 * the API package for the class.
663 */
664 private LoadedModule findLoadedModule(String mn, String cn) {
665 LoadedModule loadedModule = findLoadedModule(cn);
666 if (loadedModule != null && mn.equals(loadedModule.name())) {
667 return loadedModule;
668 } else {
669 return null;
670 }
671 }
672
673 /**
674 * Finds the class with the specified binary name if in a module
675 * defined to this ClassLoader.
676 *
677 * @return the resulting Class or {@code null} if not found
678 */
679 private Class<?> findClassInModuleOrNull(LoadedModule loadedModule, String cn) {
815 protected Package defineOrCheckPackage(String pn, Manifest man, URL url) {
816 Package pkg = getAndVerifyPackage(pn, man, url);
817 if (pkg == null) {
818 try {
819 if (man != null) {
820 pkg = definePackage(pn, man, url);
821 } else {
822 pkg = definePackage(pn, null, null, null, null, null, null, null);
823 }
824 } catch (IllegalArgumentException iae) {
825 // defined by another thread so need to re-verify
826 pkg = getAndVerifyPackage(pn, man, url);
827 if (pkg == null)
828 throw new InternalError("Cannot find package: " + pn);
829 }
830 }
831 return pkg;
832 }
833
834 /**
835 * Get the Package with the specified package name. If defined
836 * then verify that it against the manifest and code source.
837 *
838 * @throws SecurityException if there is a sealing violation (JAR spec)
839 */
840 private Package getAndVerifyPackage(String pn, Manifest man, URL url) {
841 Package pkg = getDefinedPackage(pn);
842 if (pkg != null) {
843 if (pkg.isSealed()) {
844 if (!pkg.isSealed(url)) {
845 throw new SecurityException(
846 "sealing violation: package " + pn + " is sealed");
847 }
848 } else {
849 // can't seal package if already defined without sealing
850 if ((man != null) && isSealed(pn, man)) {
851 throw new SecurityException(
852 "sealing violation: can't seal package " + pn +
853 ": already defined");
854 }
855 }
856 }
857 return pkg;
858 }
859
860 /**
861 * Defines a new package in this ClassLoader. The attributes in the specified
862 * Manifest are use to get the package version and sealing information.
863 *
864 * @throws IllegalArgumentException if the package name duplicates an
865 * existing package either in this class loader or one of its ancestors
866 */
867 private Package definePackage(String pn, Manifest man, URL url) {
868 String specTitle = null;
869 String specVersion = null;
870 String specVendor = null;
871 String implTitle = null;
872 String implVersion = null;
873 String implVendor = null;
874 String sealed = null;
875 URL sealBase = null;
876
877 if (man != null) {
878 Attributes attr = man.getAttributes(pn.replace('.', '/').concat("/"));
879 if (attr != null) {
880 specTitle = attr.getValue(Attributes.Name.SPECIFICATION_TITLE);
881 specVersion = attr.getValue(Attributes.Name.SPECIFICATION_VERSION);
882 specVendor = attr.getValue(Attributes.Name.SPECIFICATION_VENDOR);
959 if (p != null) {
960 // for directories then need recursive access
961 if (p instanceof FilePermission) {
962 String path = p.getName();
963 if (path.endsWith(File.separator)) {
964 path += "-";
965 p = new FilePermission(path, "read");
966 }
967 }
968 perms.add(p);
969 }
970 } catch (IOException ioe) { }
971
972 return perms;
973 }
974
975
976 // -- miscellaneous supporting methods
977
978 /**
979 * Returns the ModuleReader for the given module, creating it if needed
980 */
981 private ModuleReader moduleReaderFor(ModuleReference mref) {
982 ModuleReader reader = moduleToReader.get(mref);
983 if (reader == null) {
984 // avoid method reference during startup
985 Function<ModuleReference, ModuleReader> create = new Function<>() {
986 public ModuleReader apply(ModuleReference moduleReference) {
987 try {
988 return mref.open();
989 } catch (IOException e) {
990 // Return a null module reader to avoid a future class
991 // load attempting to open the module again.
992 return new NullModuleReader();
993 }
994 }
995 };
996 reader = moduleToReader.computeIfAbsent(mref, create);
997 }
998 return reader;
999 }
|
567 return findClassOnClassPathOrNull(cn);
568 }
569
570 return null;
571 }
572
573 /**
574 * Loads the class with the specified binary name.
575 */
576 @Override
577 protected Class<?> loadClass(String cn, boolean resolve)
578 throws ClassNotFoundException
579 {
580 Class<?> c = loadClassOrNull(cn, resolve);
581 if (c == null)
582 throw new ClassNotFoundException(cn);
583 return c;
584 }
585
586 /**
587 * A variation of {@code loadClass} to load a class with the specified
588 * binary name. This method returns {@code null} when the class is not
589 * found.
590 */
591 protected Class<?> loadClassOrNull(String cn, boolean resolve) {
592 synchronized (getClassLoadingLock(cn)) {
593 // check if already loaded
594 Class<?> c = findLoadedClass(cn);
595
596 if (c == null) {
597
598 // find the candidate module for this class
599 LoadedModule loadedModule = findLoadedModule(cn);
600 if (loadedModule != null) {
601
602 // package is in a module
603 BuiltinClassLoader loader = loadedModule.loader();
604 if (loader == this) {
605 if (VM.isModuleSystemInited()) {
606 c = findClassInModuleOrNull(loadedModule, cn);
607 }
616 if (parent != null) {
617 c = parent.loadClassOrNull(cn);
618 }
619
620 // check class path
621 if (c == null && hasClassPath() && VM.isModuleSystemInited()) {
622 c = findClassOnClassPathOrNull(cn);
623 }
624 }
625
626 }
627
628 if (resolve && c != null)
629 resolveClass(c);
630
631 return c;
632 }
633 }
634
635 /**
636 * A variation of {@code loadClass} to load a class with the specified
637 * binary name. This method returns {@code null} when the class is not
638 * found.
639 */
640 protected Class<?> loadClassOrNull(String cn) {
641 return loadClassOrNull(cn, false);
642 }
643
644 /**
645 * Finds the candidate loaded module for the given class name.
646 * Returns {@code null} if none of the modules defined to this
647 * class loader contain the API package for the class.
648 */
649 private LoadedModule findLoadedModule(String cn) {
650 int pos = cn.lastIndexOf('.');
651 if (pos < 0)
652 return null; // unnamed package
653
654 String pn = cn.substring(0, pos);
655 return packageToModule.get(pn);
656 }
657
658 /**
659 * Finds the candidate loaded module for the given class name
660 * in the named module. Returns {@code null} if the named module
661 * is not defined to this class loader or does not contain
662 * the API package for the class.
663 */
664 private LoadedModule findLoadedModule(String mn, String cn) {
665 LoadedModule loadedModule = findLoadedModule(cn);
666 if (loadedModule != null && mn.equals(loadedModule.name())) {
667 return loadedModule;
668 } else {
669 return null;
670 }
671 }
672
673 /**
674 * Finds the class with the specified binary name if in a module
675 * defined to this ClassLoader.
676 *
677 * @return the resulting Class or {@code null} if not found
678 */
679 private Class<?> findClassInModuleOrNull(LoadedModule loadedModule, String cn) {
815 protected Package defineOrCheckPackage(String pn, Manifest man, URL url) {
816 Package pkg = getAndVerifyPackage(pn, man, url);
817 if (pkg == null) {
818 try {
819 if (man != null) {
820 pkg = definePackage(pn, man, url);
821 } else {
822 pkg = definePackage(pn, null, null, null, null, null, null, null);
823 }
824 } catch (IllegalArgumentException iae) {
825 // defined by another thread so need to re-verify
826 pkg = getAndVerifyPackage(pn, man, url);
827 if (pkg == null)
828 throw new InternalError("Cannot find package: " + pn);
829 }
830 }
831 return pkg;
832 }
833
834 /**
835 * Gets the Package with the specified package name. If defined
836 * then verifies it against the manifest and code source.
837 *
838 * @throws SecurityException if there is a sealing violation (JAR spec)
839 */
840 private Package getAndVerifyPackage(String pn, Manifest man, URL url) {
841 Package pkg = getDefinedPackage(pn);
842 if (pkg != null) {
843 if (pkg.isSealed()) {
844 if (!pkg.isSealed(url)) {
845 throw new SecurityException(
846 "sealing violation: package " + pn + " is sealed");
847 }
848 } else {
849 // can't seal package if already defined without sealing
850 if ((man != null) && isSealed(pn, man)) {
851 throw new SecurityException(
852 "sealing violation: can't seal package " + pn +
853 ": already defined");
854 }
855 }
856 }
857 return pkg;
858 }
859
860 /**
861 * Defines a new package in this ClassLoader. The attributes in the specified
862 * Manifest are used to get the package version and sealing information.
863 *
864 * @throws IllegalArgumentException if the package name duplicates an
865 * existing package either in this class loader or one of its ancestors
866 */
867 private Package definePackage(String pn, Manifest man, URL url) {
868 String specTitle = null;
869 String specVersion = null;
870 String specVendor = null;
871 String implTitle = null;
872 String implVersion = null;
873 String implVendor = null;
874 String sealed = null;
875 URL sealBase = null;
876
877 if (man != null) {
878 Attributes attr = man.getAttributes(pn.replace('.', '/').concat("/"));
879 if (attr != null) {
880 specTitle = attr.getValue(Attributes.Name.SPECIFICATION_TITLE);
881 specVersion = attr.getValue(Attributes.Name.SPECIFICATION_VERSION);
882 specVendor = attr.getValue(Attributes.Name.SPECIFICATION_VENDOR);
959 if (p != null) {
960 // for directories then need recursive access
961 if (p instanceof FilePermission) {
962 String path = p.getName();
963 if (path.endsWith(File.separator)) {
964 path += "-";
965 p = new FilePermission(path, "read");
966 }
967 }
968 perms.add(p);
969 }
970 } catch (IOException ioe) { }
971
972 return perms;
973 }
974
975
976 // -- miscellaneous supporting methods
977
978 /**
979 * Returns the ModuleReader for the given module, creating it if needed.
980 */
981 private ModuleReader moduleReaderFor(ModuleReference mref) {
982 ModuleReader reader = moduleToReader.get(mref);
983 if (reader == null) {
984 // avoid method reference during startup
985 Function<ModuleReference, ModuleReader> create = new Function<>() {
986 public ModuleReader apply(ModuleReference moduleReference) {
987 try {
988 return mref.open();
989 } catch (IOException e) {
990 // Return a null module reader to avoid a future class
991 // load attempting to open the module again.
992 return new NullModuleReader();
993 }
994 }
995 };
996 reader = moduleToReader.computeIfAbsent(mref, create);
997 }
998 return reader;
999 }
|