AdoptOpenJDK / IcedTea-Web

The new home for IcedTea-Web
Other
225 stars 85 forks source link

Extension JNLP cache entries causes NPE on version change #932

Closed tzjan closed 7 months ago

tzjan commented 8 months ago

running: OpenWebstart 1.9.1 (icedtea-web-2.0.0-alpha29)

After an application update with a version increase of all our JNLP resources (including the extension), we have got the following NPE:

net.sourceforge.jnlp.LaunchException: Fatal: Initialization Error: Could not initialize application. The application has not been initialized, for more information execute javaws from the command line.
    at net.sourceforge.jnlp.Launcher.createApplication(Launcher.java:593)
    at net.sourceforge.jnlp.Launcher.launchApplication(Launcher.java:374)
    at net.sourceforge.jnlp.Launcher.access$300(Launcher.java:72)
    at net.sourceforge.jnlp.Launcher$TgThread.run(Launcher.java:661)
Caused by: java.lang.RuntimeException: java.lang.Exception: Exception while initializing extension 'http://localhost:8080/webapp/jnlp.extension/common.jnlp'
    at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.initializeExtensions(JNLPClassLoader.java:575)
    at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.<init>(JNLPClassLoader.java:350)
    at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.createInstance(JNLPClassLoader.java:425)
    at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.getInstance(JNLPClassLoader.java:497)
    at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.getInstance(JNLPClassLoader.java:470)
    at net.sourceforge.jnlp.Launcher.createApplication(Launcher.java:585)
    ... 3 more
Caused by: java.lang.Exception: Exception while initializing extension 'http://localhost:8080/webapp/jnlp.extension/common.jnlp'
    at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.initializeExtensions(JNLPClassLoader.java:568)
    ... 8 more
Caused by: java.io.IOException: java.lang.NullPointerException: name can't be null
    at net.sourceforge.jnlp.JNLPFileFactory.openURL(JNLPFileFactory.java:107)
    at net.sourceforge.jnlp.JNLPFileFactory.create(JNLPFileFactory.java:79)
    at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.getInstance(JNLPClassLoader.java:542)
    at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.initializeExtensions(JNLPClassLoader.java:565)
    ... 8 more
Caused by: java.lang.NullPointerException: name can't be null
    at java.base/java.io.FilePermission.init(Unknown Source)
    at java.base/java.io.FilePermission.<init>(Unknown Source)
    at java.base/java.lang.SecurityManager.checkRead(Unknown Source)
    at java.base/java.io.FileInputStream.<init>(Unknown Source)
    at net.sourceforge.jnlp.JNLPFileFactory.openURL(JNLPFileFactory.java:103)
    ... 11 more

The code tries to lookup the new version 6.2.4 of the extension JNLP file http://localhost:8080/webapp/jnlp.extension/common.jnlp in the cache. recently_used.cache contains 2 entries:

::i=0\21::l=http://localhost:8080/webapp/jnlp.extension/common.jnlp::a=1706792384190::
...
::i=0\0::l=http://localhost:8080/webapp/jnlp.extension/common.jnlp::v=6.2.3::a=1706792354511::

The NPE is thrown at line 246 in CacheImpl.java because one Cache entry doesn't contain a version information.

https://github.com/AdoptOpenJDK/IcedTea-Web/blob/a3d166d595328bc6080667ef49c395054eed7ea6/core/src/main/java/net/adoptopenjdk/icedteaweb/resources/cache/CacheImpl.java#L241-L247

So why does 2 versions of the extension JNLP exists in the cache? It shouldn't because the extension is defined my JNLP file with a version number:

   <extension name="common" version="6.2.3" href="http://localhost:8080/webapp/jnlp.extension/common.jnlp" />

To understand this I rolled back to the former application version 6.2.3 and cleared the cache.

At first the following entry will be created in private void initializeExtensions() by /IcedTea-Web/core/src/main/java/net/sourceforge/jnlp/runtime/classloader/JNLPClassLoader.java.

recently_used.cache:

::i=0\0::l=http://localhost:8080/webapp/jnlp.extension/common.jnlp::v=6.2.3::a=1706878820432::

Looks fine. Later 'http://localhost:8080/webapp/jnlp.extension/common.jnlp' will be looked up again, but without version, see stack trace: https://github.com/AdoptOpenJDK/IcedTea-Web/blob/a3d166d595328bc6080667ef49c395054eed7ea6/core/src/main/java/net/adoptopenjdk/icedteaweb/jnlp/element/resource/ExtensionDesc.java#L134

--> ExtensionDesc.resolve() line: 134   
    ApplicationInstance.collectPropertiesFromJnlpHierarchy(List<PropertyDesc>, JNLPFile) line: 297  
    ApplicationInstance.installEnvironment() line: 137  
    ApplicationInstance.initialize() line: 116  

This adds a versionless entry to the cache:

::i=0\21::l=http://localhost:8080/webapp/jnlp.extension/common.jnlp::a=1706881064943::
...
::i=0\0::l=http://localhost:8080/webapp/jnlp.extension/common.jnlp::v=6.2.4::a=1706878820432::

Unless the version is not changed this works fine, but when it changes all.sort(versionComparator) fails.

Despite of having such a deep understanding of the application, I think 2 things should be changed:

  1. The sorting should be fixed. I don't have a clue how it should be handled. A unversioned cache request, should only return unversioned candidates? A versioned cache request, should only return versioned candidates?

  2. The 2nd lookup should use a version, if there is one. For this I can provide a pull request for a change, which works for me.

When only the 2nd one is applied the error is still there, when the cache looks like above.

Do you have any idea how this can be fixed?

janakmulani commented 7 months ago

@tzjan thanks for reporting and analyzing. We will have a look. You may also provide a PR.

Question: Did you ever encounter this problem with earlier versions of OWS?

tzjan commented 7 months ago

@janakmulani I can reproduce the error with OWS 1.8.0 and 1.9.1.

janakmulani commented 7 months ago

@tzjan Thanks for the feedback and the PR.

tzjan commented 7 months ago

Thanks for the quick feedback