You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Thom Park <tp...@borland.com> on 2001/08/08 23:52:12 UTC

how to reload a getResourceAsStream() object

hello,

I have a requirement where i need to make multiple passes over a resource
stream
obtained via ServletContext.getResourceAsStream().

My problem is that as follows:

	InputStream is = sc.getResourceAsStream("/my_resource_name");

	.... do 1st processing pass

	is.close();

	is = sc.getResourceAsStream("/my_resource_name");

	... do second processing pass...

The problem is that, as far as the StandardClassLoader is concerned, the
cached copy of the input stream is still good (and it isn't I just closed
it)
and I get the original (now bad) input stream returned.


Is there anyway to force tomcat to reload the resource object (without
unloading the context).
as, right now I'm reading the whole resource into a byte array and using
[my] cached copy
for processing.

-Thom


-----Original Message-----
From: cmanolache@yahoo.com [mailto:cmanolache@yahoo.com]
Sent: Wednesday, August 08, 2001 2:13 PM
To: tomcat dev jakarta.apache.org
Cc: pmc@jakarta.apache.org
Subject: Re: [PROPOSAL] Deprecation of committers...



Can you send a list with the commiters that will become deprecated ?

Does this include 3.x commiters as well ? ( from the proposal it seems you
are talking about 4.0 commiters ).


Costin


On Wed, 8 Aug 2001, Pier P. Fumagalli wrote:

> I recently checked the list of committers for Tomcat 4.0 and MANY of them
> are inactive... Our PMC charter mentions:
>
>   At times, Committers may go inactive for a variety of reasons. A
Committer
>   that has been inactive for 6 months or more may lose their status as a
>   Committer. Getting access back is as simple as re-requesting it on the
>   projects developer mailing list.
>
> Can we start the process for "deprecating" them?
>
>     Pier
>



RE: how to reload a getResourceAsStream() object

Posted by Remy Maucherat <re...@betaversion.org>.
Quoting Thom Park <tp...@borland.com>:

> Hmm...
> 
> so what about this line of code in StandardClassLoader:
> 
>     public InputStream getResourceAsStream(String name) {
> 
>         if (debug >= 2)
>             log("getResourceAsStream(" + name + ")");
>         InputStream stream = null;
> 
>         // (0) Check for a cached copy of this resource
>         stream = findLoadedResource(name);
>         if (stream != null) {
>             if (debug >= 2)
>                 log("  --> Returning stream from cache");
>             return (stream);
>         }...

That code won't be used if you do ServletContext.getResourceAsStream.

Also, the code in StandardClassLoader.findLoadedResource actually is :

    protected InputStream findLoadedResource(String name) {

        return (null);  // FIXME - findLoadedResource()

    }

In the new WebappClassLoader, it actually does some caching :

    protected InputStream findLoadedResource(String name) {

        ResourceEntry entry = (ResourceEntry) resourceEntries.get(name);
        if (entry != null) {
            if (entry.binaryContent != null)
                return new ByteArrayInputStream(entry.binaryContent);
        }
        return (null);

    }

but it does create a stream each time.

For the ServletContext, the thing creating the stream is the directory context 
(FileDirContext), and it also does create a new stream each time.

Remy

RE: how to reload a getResourceAsStream() object

Posted by Thom Park <tp...@borland.com>.
Hmm...

so what about this line of code in StandardClassLoader:

    public InputStream getResourceAsStream(String name) {

        if (debug >= 2)
            log("getResourceAsStream(" + name + ")");
        InputStream stream = null;

        // (0) Check for a cached copy of this resource
        stream = findLoadedResource(name);
        if (stream != null) {
            if (debug >= 2)
                log("  --> Returning stream from cache");
            return (stream);
        }...

Looks to me that if the resource has been loaded, then it stays loaded,
even if it's been closed, at least for the StandardClassLoader...

I've got a scenario where the Context.getResourceAsStream returns me a
duff stream following a close on the stream.

I accept that your testcase proves that there must be something else hosing
me
here but it's a wee bit frustrating.

I guess I need to find out what the heck is going on with this stream
nonsense.

-Thom




-----Original Message-----
From: Remy Maucherat [mailto:remy@betaversion.org]
Sent: Wednesday, August 08, 2001 3:49 PM
To: tomcat-dev@jakarta.apache.org
Subject: Re: how to reload a getResourceAsStream() object


Quoting Thom Park <tp...@borland.com>:

> hello,
>
> I have a requirement where i need to make multiple passes over a
> resource
> stream
> obtained via ServletContext.getResourceAsStream().
>
> My problem is that as follows:
>
> 	InputStream is = sc.getResourceAsStream("/my_resource_name");
>
> 	.... do 1st processing pass
>
> 	is.close();
>
> 	is = sc.getResourceAsStream("/my_resource_name");
>
> 	... do second processing pass...
>
> The problem is that, as far as the StandardClassLoader is concerned,
> the
> cached copy of the input stream is still good (and it isn't I just
> closed
> it)
> and I get the original (now bad) input stream returned.
>
>
> Is there anyway to force tomcat to reload the resource object (without
> unloading the context).
> as, right now I'm reading the whole resource into a byte array and
> using
> [my] cached copy
> for processing.

Ok, but :
- SevletContext.getResourceAsStream != ClassLoader.getResourceAsStream. If
you
use the servlet context, it has nothing to do at all with any class loader.
- I modified the HelloWorldServlet from the examples webapp just to be sure,
and inserted :

        byte[] b = new byte[4096];
        InputStream is = getServletContext().getResourceAsStream
("/servlets/index.html");
        while (true) {
            int n = is.read(b);
            if (n == -1)
                break;
            System.out.println("Read1: " + n);
        }
        is.close();

        is =
getServletContext().getResourceAsStream("/servlets/index.html");
        while (true) {
            int n = is.read(b);
            if (n == -1)
                break;
            System.out.println("Read2: " + n);
        }
        is.close();

The display on the standard out is :

Read1: 4096
Read1: 892
Read2: 4096
Read2: 892

So it's working fine for me.

Using getResourceAsStream on the classloader should work the same (it will
end
up using URL.openStream which will in turn call Resource.streamContent, just
like ServletContext.getResourceAsStream).

Remy


Re: how to reload a getResourceAsStream() object

Posted by Remy Maucherat <re...@betaversion.org>.
Quoting Thom Park <tp...@borland.com>:

> hello,
> 
> I have a requirement where i need to make multiple passes over a
> resource
> stream
> obtained via ServletContext.getResourceAsStream().
> 
> My problem is that as follows:
> 
> 	InputStream is = sc.getResourceAsStream("/my_resource_name");
> 
> 	.... do 1st processing pass
> 
> 	is.close();
> 
> 	is = sc.getResourceAsStream("/my_resource_name");
> 
> 	... do second processing pass...
> 
> The problem is that, as far as the StandardClassLoader is concerned,
> the
> cached copy of the input stream is still good (and it isn't I just
> closed
> it)
> and I get the original (now bad) input stream returned.
> 
> 
> Is there anyway to force tomcat to reload the resource object (without
> unloading the context).
> as, right now I'm reading the whole resource into a byte array and
> using
> [my] cached copy
> for processing.

Ok, but :
- SevletContext.getResourceAsStream != ClassLoader.getResourceAsStream. If you 
use the servlet context, it has nothing to do at all with any class loader.
- I modified the HelloWorldServlet from the examples webapp just to be sure, 
and inserted :

        byte[] b = new byte[4096];
        InputStream is = getServletContext().getResourceAsStream
("/servlets/index.html");
        while (true) {
            int n = is.read(b);
            if (n == -1)
                break;
            System.out.println("Read1: " + n);
        }
        is.close();

        is = getServletContext().getResourceAsStream("/servlets/index.html");
        while (true) {
            int n = is.read(b);
            if (n == -1)
                break;
            System.out.println("Read2: " + n);
        }
        is.close();

The display on the standard out is :

Read1: 4096
Read1: 892
Read2: 4096
Read2: 892

So it's working fine for me.

Using getResourceAsStream on the classloader should work the same (it will end 
up using URL.openStream which will in turn call Resource.streamContent, just 
like ServletContext.getResourceAsStream).

Remy

Re: how to reload a getResourceAsStream() object

Posted by "Pier P. Fumagalli" <pi...@betaversion.org>.
Thom Park at tpark@borland.com wrote:

> hello,
> 
> I have a requirement where i need to make multiple passes over a resource
> stream
> obtained via ServletContext.getResourceAsStream().
> 
> My problem is that as follows:
> 
> InputStream is = sc.getResourceAsStream("/my_resource_name");
> 
> .... do 1st processing pass
> 
> is.close();
> 
> is = sc.getResourceAsStream("/my_resource_name");
> 
> ... do second processing pass...
> 
> The problem is that, as far as the StandardClassLoader is concerned, the
> cached copy of the input stream is still good (and it isn't I just closed
> it)
> and I get the original (now bad) input stream returned.
> 
> 
> Is there anyway to force tomcat to reload the resource object (without
> unloading the context).
> as, right now I'm reading the whole resource into a byte array and using
> [my] cached copy
> for processing.

Seems to be a bug in the classloader implementation. When the resource
inputstream is closed, and you get another one, you should get a fresh new
working stream...

    Pier