Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-5624

Remoting does not retrieve resources in locally pre-fetched JARs

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Minor Minor
    • core, remoting
    • None

      Hudson remoting does not retrieve resources in locally pre-fetched JARs. Though this is a minor performance issue, it causes some Java APIs to break.

      For example, a Java API used in a Callable might expect that certain resources exist in the same JAR. So, to make the API happy, the Callable will use the PreloadJarTask to get the JAR pre-loaded on the client. With the current Hudson remoting, each resource retrieval causes the resource to be copied to a local file without considering whether it resides in a pre-loaded JAR.

      Consider a callable that uses the Java API called ReallyCool. Assume ReallyCool has a method named execute and we've pre-loaded all JARs containing logo.png:

      01: public static void execute() {
      02:
      03:    // This call will cause every resource with the name logo.png
      04:    // to be downloaded from the server and stored as a local
      05:    // file. This should be fixed so that it first checks if any
      06:    // of the pre-loaded JARs have the resource before downloading
      07:    // them from the server.
      08:
      09:    Enumeration<URL> logo = classLoader.getResources("logo.png");
      10:
      11:    while (logo.hasMoreElements()) {
      12:        String urlspec = logo.nextElement().toExternalForm();
      13:        urlspec = urlspec.replace("logo.png", "META-INF/MANIFEST.MF");
      14:        URL manifest = new URL(urlspec);
      15:        InputStream stream manifest.openStream();
      16:        // Oh, no: stream is null since the URL isn't alongside
      17:        // logo in the same directory.
      18:    }
      19: }
      

      With the current implementation, the following will happen.

      In line 12, logo's URL will be something like: jar:file:/tmp/hudson-remoting1234/logo.png. This is because the RemoteClassLoader findResources() method always downloads resources from the server without considering the pre-loaded JARs.

      When the manifest URL is created in lines 13-15, it will be: jar:file:/tmp/hudson-remoting1234/META-INF/MANIFEST.MF. When we attempt to open a stream on it, the stream will be null since that file does not exist.

      However, since we pre-loaded it, we expect the lookups of logo.png in line 12 to be like: jar:file:/tmp/hudson-remoting5678/important.jar!/logo.png. Then, the code above that looks up the manifest file in lines 13-15 will work properly since important.jar will exist locally.

      I provided a unit test, RemoteClassLoaderTest, that tests this functionality and illustrates the failure.

            Unassigned Unassigned
            frankjacobs frankjacobs
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: