knopflerfish / knopflerfish.org

Knopflerfish OSGi Service Platform. OSGi run-time container and SDK source code repo
http://www.knopflerfish.org
BSD 3-Clause "New" or "Revised" License
33 stars 11 forks source link

Avoid NoSuchElementException #44

Closed dpolivaev closed 6 years ago

dpolivaev commented 6 years ago

If bundle class loader should find a resource from package loaded by application class loader and this resource is not available, it currently throws NoSuchElementException instead of returning null.

Exception in thread "main" 
java.util.NoSuchElementException
    at sun.misc.CompoundEnumeration.nextElement(CompoundEnumeration.java:59)
    at org.knopflerfish.framework.BundleClassLoader.findResource(BundleClassLoader.java:213)
    at org.knopflerfish.framework.BundleClassLoader.getResource(BundleClassLoader.java:391)
    at org.freeplane.launcher.Launcher.launchWithoutUICheck(Launcher.java:279)

It happens because it delegates to application class loader

<init>:39, CompoundEnumeration (sun.misc)
getResources:1144, ClassLoader (java.lang)
frameworkSearchFor:887, BundleClassLoader (org.knopflerfish.framework)
searchFor0:715, BundleClassLoader (org.knopflerfish.framework)
searchFor:613, BundleClassLoader (org.knopflerfish.framework)
run:561, SecurePermissionOps$3 (org.knopflerfish.framework)
doPrivileged:-1, AccessController (java.security)
callSearchFor:558, SecurePermissionOps (org.knopflerfish.framework)
getBundleResources:513, BundleClassLoader (org.knopflerfish.framework)
findResource:211, BundleClassLoader (org.knopflerfish.framework)
getResource:391, BundleClassLoader (org.knopflerfish.framework)
launchWithoutUICheck:279, Launcher (org.freeplane.launcher)
main:75, Launcher (org.freeplane.launcher)

which can return non null enumeration which is empty.

The pull request adds a check for this case.

dpolivaev commented 6 years ago

(the version of freeplane launcher containing this call to getResource is not submitted to git, it was only created for test. The exception is thrown from line URL resource = classLoader.getResource(foo);)

    private Controller launchWithoutUICheck(String[] args) {
        if(freeplaneLaunched)
            throw new IllegalStateException("Freeplane already launched");
        freeplaneLaunched = true;
        setDefines();
        if (! disableSecurityManager)
            System.setSecurityManager(new SecurityManager(){

                @Override
                public void checkConnect(String pHost, int pPort, Object pContext) {
                    if(pContext != null)
                        super.checkConnect(pHost, pPort, pContext);
                    else
                        super.checkConnect(pHost, pPort);
                }

            });
        setArgProperties(args);
        final Controller controller = startFramework();
        ClassLoader classLoader = controller.getClass().getClassLoader();
        String foo = Controller.class.getPackage().getName().replace('.', '/') + '/' + "foo.txt";
        URL resource = classLoader.getResource(foo);
        return controller;
    }
chlarsson commented 6 years ago

Thanks for the PR. We'll have a closer look at it in a day or two.

Thanks, Christer

janste63 commented 6 years ago

Thanks for the fix.