Menu

#2 Cope with clients who get resource streams multiple times

fixes
open
nobody
General (2)
5
2007-01-25
2007-01-25
Anonymous
No

Hi,

Some client bundles may access the same resource stream several times by repeatedly calling openConnection() on the URL, before actually reading data from it.

Unfortunately, the internal BundleURLHandler class that provides openConnection() always returns the original resource InputStream. This means that if a client calls openConnection(), then for some reason closes the given stream, and finally calls openConnection() again on the same resource to grab the data, it won't get anything back because the single stream is now closed.

The proper fix is to store the relevant file details in the BundleURLHandler instance, so it can call retrieveFile() to create a new InputStream for every call to openConnection().

Another solution, which avoids creating new InputStreams and fixes the above scenario (but won't work in the general case!) is to only close the stream if the client has actually read data from it.

Note that this *will* leak connections if a client opens resources, but never reads from them ... anyway, just wanted to share this patch in case you found it useful.

Cheers, Stuart McCulloch

mcculls@gmail.com

Discussion

  • Nobody/Anonymous

    Patch for BundleClassLoader.java

     
  • Nobody/Anonymous

    Logged In: NO

    An alternative patch which won't leak connections but doesn't cache the original InputStream:

    Index: framework/src/ch/ethz/iks/concierge/framework/BundleClassLoader.java

    --- framework/src/ch/ethz/iks/concierge/framework/BundleClassLoader.java (revision 47)
    +++ framework/src/ch/ethz/iks/concierge/framework/BundleClassLoader.java (working copy)
    @@ -711,8 +711,9 @@
    final InputStream inputStream = retrieveFile(jarFile,
    classpath[i], storageLocation, name);
    if (inputStream != null) {
    - results.add(new URL("bundle", name, 0, "",
    - new BundleURLHandler(inputStream)));
    + inputStream.close(); // no longer cached
    + results.add(new URL("bundle", null, 0, name,
    + new BundleURLHandler(classpath[i])));
    if (!multiple) {
    return results;
    }
    @@ -1050,25 +1051,25 @@
    }

    /**
    - * the "degenerated" URL handler that already contains the InputStream of
    - * the URL and returns this InputStream on demand.
    + * a simple URL handler for the named resource, which retrieves a
    + * new InputStream instance for every call to openConnection()
    *
    * @author Jan S. Rellermeyer, IKS, ETH Zurich
    */
    - private static final class BundleURLHandler extends URLStreamHandler {
    + private final class BundleURLHandler extends URLStreamHandler {
    /**
    - * the embedded input stream.
    + * the classpath entry holding the resource
    */
    - private final InputStream input;
    + private final String classpathEntry;

    /**
    - * create a new BundleURLHandler from an input stream.
    + * create a new BundleURLHandler for a named resource.
    *
    - * @param stream
    - * the input stream.
    + * @param entry
    + * the classpath entry holding the resource.
    */
    - private BundleURLHandler(final InputStream stream) {
    - input = stream;
    + private BundleURLHandler(final String entry) {
    + classpathEntry = entry;
    }

    /**
    @@ -1093,7 +1094,7 @@
    * @category URLConnection
    */
    public InputStream getInputStream() throws IOException {
    - return input;
    + return retrieveFile(jarFile, classpathEntry, storageLocation, url.getFile());
    }

    /**
    @@ -1120,7 +1121,7 @@
    * @category URLStreamHandler
    */
    protected int hashCode(final URL u) {
    - return input.hashCode();
    + return classpathEntry.hashCode() ^ u.getFile().hashCode();
    }
    }
    }

     
  • Jan S. Rellermeyer

    Logged In: YES
    user_id=1368628
    Originator: NO

    Hi Stuart,

    I was not aware of this so far but this is a serious bug. It should be definitly possible to access a resource more than one time. I considered the way of holding the input stream inside the BundleURLHandler as an optimization since otherwise, the resource has to be looked up twice: Once for creating the BundleURLHandler and once when a bundle actually makes use of the resouce by opening the connection. I will have a look at the code and think about how this can be fixed without loosing efficiency. Thanks for submitting your patches, they will be certainly helpful.

    Cheers,

    Jan.

     

Log in to post a comment.

MongoDB Logo MongoDB