Velocity Reviews > Java > Jar: protocol question

# Jar: protocol question

Rhino
Guest
Posts: n/a

 10-29-2005
I've been using the Jar: protocol a bit in the last few days and I'd like to
know if this is a valid use of that protocol:

jar:file:!/Images/foo.gif

Basically, I'm trying to describe the location of a GIF that a program
should be able to find in one of the various jars that are on the classpath
used by the program.

Since 'this.getClass().getResource()' will search EVERY jar in the classpath
for the desired file, it shouldn't be necessary to specify the jar name.
Therefore, it seems to me that this should be valid notation for indicating
that the jar name isn't necessary in this case: the bang ('!') in the name
following the 'file:' suggests to me that the default jar(s), namely all of
the jars found in the classpath, will be searched for an Images directory
and a file named foo.gif within that directory.

Does that seem reasonable? If not, can anyone suggest a better notation to
use for my situation?

I can't find any discussion of this "special case" in the articles I've seen

--
Rhino
---
rhino1 AT sympatico DOT ca
"There are two ways of constructing a software design. One way is to make it
so simple that there are obviously no deficiencies. And the other way is to
make it so complicated that there are no obvious deficiencies." - C.A.R.
Hoare

Ben_
Guest
Posts: n/a

 10-29-2005
If you need to load the resource from the classpath, then
this.getClass().getResource() will do the trick. What you need to know to
load it is "Images/foo.gif" and the method returns the location of the
resource (wherever it is found first).

If you know in advance there is a risk of collision (the resource exists
multiple times on the classpath and you don't want to load it from the first
location found), then you better change the location to make it unique...

Or, I don't see the point of your question...

Rhino
Guest
Posts: n/a

 10-29-2005

"Ben_" <(E-Mail Removed)> wrote in message
news:4363a271$0$432$(E-Mail Removed) et.net... > If you need to load the resource from the classpath, then > this.getClass().getResource() will do the trick. What you need to know to > load it is "Images/foo.gif" and the method returns the location of the > resource (wherever it is found first). > > If you know in advance there is a risk of collision (the resource exists > multiple times on the classpath and you don't want to load it from the first > location found), then you better change the location to make it unique... > > Or, I don't see the point of your question... > Yeah, sorry, I probably didn't ask the clearest question in the world.... I understand how this.getClass().getResource() works. My question is really one of notation more than anything. I think One of the articles I saw on the jar: protocol - I can't find it again now, unfortunately! - contained examples like this: - jar:file:d:\\myJars\\test.jar!/images/foo.gif (refers to a specific file, foo.gif, in the path 'images' within a jar called 'test.jar' in the directory d:\myJars on the local filesystem. - jar:http://xyz.com/photos/pictures.jar!/pix/baz.jpg (refers to a specific file, baz.jpg, in the page 'pix', within a jar called 'pictures.jar' in the directory 'photos' on the website at http://xyz.com. I'm looking for a notation that I can use in my programs to refer to files that are within jars that are visible to the program by virtue of being on the program's classpath. In that case, the name of the jar isn't necessary since all jars in the classpath will be scanned for the file. That's why I was thinking that 'jar:file:!/images/foo.png' would be good since it imitates the first example and implies that the file is in the file system but that we don't care what jar contains the file. When I parse a String like that last example, I merely have to start at the position immediately following the bang and use the rest of the String to build my URL. Then, the file is found or not found as the case may be. Does this seem like a reasonable notation to use or is there actually an "official" way of saying the same thing? The documentation I've seen has no information on how to denote a file in a jar when you don't care what jar file contains it. Rhino Ben_ Guest Posts: n/a  10-29-2005 Let's say you want to store an identifier for the resource in a config file. Then why not simply store "Images/foo.gif" and pass that String directly to this.getClass().getResource() ? It will lookup the classpath and load the resource from the file system or from a jar (or from a URL, if it's a URLClassLoader). So, I still not fully understand why you really insist on the fact that it has to be found in a jar file ? It's exactly the point of ClassLoaders to make you ignorant of where the resource is, provided it is on the classpath. Rhino Guest Posts: n/a  10-29-2005 "Ben_" <(E-Mail Removed)> wrote in message news:4363bb3e$0$440$(E-Mail Removed) et.net...
> Let's say you want to store an identifier for the resource in a config

file.
>
> Then why not simply store "Images/foo.gif" and pass that String directly

to
> this.getClass().getResource() ?
>
> It will lookup the classpath and load the resource from the file system or
> from a jar (or from a URL, if it's a URLClassLoader).
>
> So, I still not fully understand why you really insist on the fact that it
> has to be found in a jar file ? It's exactly the point of ClassLoaders to
> make you ignorant of where the resource is, provided it is on the

classpath.
>

If I only stored "Images/foo.gif" in config file, someone looking at the
code would have to *INFER* that it was in a jar and was going to be obtained
via this.getClass().getResource(). But what if I wanted to be able to
specify a file that wasn't necessarily in the classpath? The file could be
anywhere, even online or elsewhere in the file system.

"Images/foo.gif" is not going to be found by the program if it is *not* in a
jar on the classpath. In fact, I wouldn't be able to use
this.getClass().getResource() to find it; if it was in a standalone file in
the file system, I'd do this:

File myFile = new File(filename);
URL fileURL = myFile.toURL();

It seems to me that if you clearly and unambiguously notate the origins of a
file, including the protocol name and the jar name (where applicable!) as
well as the path(s) and the specific file name, anyone maintaining the code
is going to be very clear on exactly where that file is. The only wrinkle is
that I'm not aware of a standard way of saying that a file is in a jar on
the classpath and we don't need to know the jar name. That's why I'm
proposing the notation that I mentioned.

However, for all I know, there is already an existing convention to get the
same idea across which differs from mine. If so, I'd like to use the already
established notation, whatever it is, rather than muddying the waters by
using a different notation.

In a sense, I suppose this is basically about making the code both
self-documenting and flexible. Rather than relying on someone to write and
maintain comments in your imaginary config file saying that the file is
found in a jar on the classpath, I'd like to be able to point to any file in
the file system or online (or in a jar that is in the filesystem or online
or in the classpath) and be confident that program would use the appropriate
methods to find the file based on the way the file location was notated.

Am I making sense yet?

I'm glad we're having this dialog, it is helping me clarify in my own mind
what I'm trying to accomplish and why it seems useful.

Rhino

Thomas Fritsch
Guest
Posts: n/a

 10-30-2005
"Rhino" <(E-Mail Removed)> wrote:
> I've been using the Jar: protocol a bit in the last few days and I'd like
> to know if this is a valid use of that protocol:
>
> jar:file:!/Images/foo.gif

AFAIK the JAR-URL-specification requires the part between "jar:" and "!" to
be a valid URL, i.e. the URL of the jar file. In your case this part is
"file:" which surely is invalid. Hence, in my opinion it would be a mis-use
of the "jar:" protocol.
>
> Basically, I'm trying to describe the location of a GIF that a program
> should be able to find in one of the various jars that are on the
> classpath
> used by the program.
>
> Since 'this.getClass().getResource()' will search EVERY jar in the
> classpath
> for the desired file, it shouldn't be necessary to specify the jar name.
> Therefore, it seems to me that this should be valid notation for
> indicating
> that the jar name isn't necessary in this case: the bang ('!') in the name
> following the 'file:' suggests to me that the default jar(s), namely all
> of
> the jars found in the classpath, will be searched for an Images directory
> and a file named foo.gif within that directory.
>
> Does that seem reasonable? If not, can anyone suggest a better notation to
> use for my situation?

Yes, sure. It is a reasonable thing to want.
But I would suggest not to use the "jar:" protocol, and instead prefer to
invent a new
protocol (the name "classpath:" comes to mind). Example URLs might then be:
classpath:/Images/foo.gif
classpath:/javax/swing/plaf/metal/icons/Error.gif

You can push this approach even one step further. If you would write a small
Handler for this new protocol, then you could use your new URLs exactly like
any other URL. For example:
URL url = new URL("classpath:/Images/foo.gif");
InputStream stream = url.openStream();
More on protocol handlers can be found at
http://java.sun.com/j2se/1.4.2/docs/...tructor_detail
>
> I can't find any discussion of this "special case" in the articles I've
> seen
>

--
"TFritsch$t-online:de".replace(':','.').replace('$','@')

Roedy Green
Guest
Posts: n/a

 10-30-2005
On Sat, 29 Oct 2005 11:20:01 -0400, "Rhino"
<(E-Mail Removed)> wrote, quoted or indirectly
quoted someone who said :

>Since 'this.getClass().getResource()' will search EVERY jar in the classpath
>for the desired file, it shouldn't be necessary to specify the jar name.
>Therefore, it seems to me that this should be valid notation for indicating
>that the jar name isn't necessary in this case: the bang ('!') in the name
>following the 'file:' suggests to me that the default jar(s), namely all of
>the jars found in the classpath, will be searched for an Images directory
>and a file named foo.gif within that directory.

getResource does a search and gives you a direct url to the Jar where
it found the resource.

If you want to speed that search, use the class-path and index
feature of jar.exe to build a multi-jar index for direct lookup.
--
http://mindprod.com Java custom programming, consulting and coaching.

Roedy Green
Guest
Posts: n/a

 10-30-2005
On Sat, 29 Oct 2005 13:11:04 -0400, "Rhino"
<(E-Mail Removed)> wrote, quoted or indirectly
quoted someone who said :

>I'm looking for a notation that I can use in my programs to refer to files
>that are within jars that are visible to the program by virtue of being on
>the program's classpath. In that case, the name of the jar isn't necessary
>since all jars in the classpath will be scanned for the file. That's why I
>was thinking that 'jar:file:!/images/foo.png' would be good since it
>imitates the first example and implies that the file is in the file system
>but that we don't care what jar contains the file.

getResource does searching and gives you the FIRST resource match on
the classpath.

It produces the !syntax which is treated thereafter like any other
URL.

You want a method something like this off the top of my head:

/**
@param s either resource or URL to resource
code either as "myimage.jpg"
or as "jar:file:///C|/bar/baz.jar!/com/foo/myimage.jpg"
@eturn URL to resource
*/
getURLForResource( Class c, String s )
{
if ( s.startsWith( "jar:" )
|| s.startsWith( "file:" )
|| s.startsWith( "http:" ) )
return new URL( s );
else return c.getResource( s );
}
--
http://mindprod.com Java custom programming, consulting and coaching.

Roedy Green
Guest
Posts: n/a

 10-30-2005
On Sat, 29 Oct 2005 14:59:38 -0400, "Rhino"
<(E-Mail Removed)> wrote, quoted or indirectly
quoted someone who said :

>If I only stored "Images/foo.gif" in config file, someone looking at the
>code would have to *INFER* that it was in a jar and was going to be obtained
>via this.getClass().getResource().

Experienced Java programmers all know what a resource is, and are used
to adjusting file locations external to the program to have them still
considered resources in different contexts, e.g. debugging, running
locally, running on a server, running as an Applet.

If you start monkeying with that, you are going to cause 100 times as
much confusion as you imagine you are avoiding.
--
http://mindprod.com Java custom programming, consulting and coaching.

Rhino
Guest
Posts: n/a

 10-30-2005

"Thomas Fritsch" <(E-Mail Removed)> wrote in message
news:dk1arj$cro$01\$(E-Mail Removed)-online.com...
> "Rhino" <(E-Mail Removed)> wrote:
> > I've been using the Jar: protocol a bit in the last few days and I'd

like
> > to know if this is a valid use of that protocol:
> >
> > jar:file:!/Images/foo.gif

> AFAIK the JAR-URL-specification requires the part between "jar:" and "!"

to
> be a valid URL, i.e. the URL of the jar file. In your case this part is
> "file:" which surely is invalid. Hence, in my opinion it would be a

mis-use
> of the "jar:" protocol.
> >
> > Basically, I'm trying to describe the location of a GIF that a program
> > should be able to find in one of the various jars that are on the
> > classpath
> > used by the program.
> >
> > Since 'this.getClass().getResource()' will search EVERY jar in the
> > classpath
> > for the desired file, it shouldn't be necessary to specify the jar name.
> > Therefore, it seems to me that this should be valid notation for
> > indicating
> > that the jar name isn't necessary in this case: the bang ('!') in the

name
> > following the 'file:' suggests to me that the default jar(s), namely all
> > of
> > the jars found in the classpath, will be searched for an Images

directory
> > and a file named foo.gif within that directory.
> >
> > Does that seem reasonable? If not, can anyone suggest a better notation

to
> > use for my situation?

> Yes, sure. It is a reasonable thing to want.
> But I would suggest not to use the "jar:" protocol, and instead prefer to
> invent a new
> protocol (the name "classpath:" comes to mind). Example URLs might then

be:
> classpath:/Images/foo.gif
> classpath:/javax/swing/plaf/metal/icons/Error.gif
>
> You can push this approach even one step further. If you would write a

small
> Handler for this new protocol, then you could use your new URLs exactly

like
> any other URL. For example:
> URL url = new URL("classpath:/Images/foo.gif");
> InputStream stream = url.openStream();
> More on protocol handlers can be found at
>

http://java.sun.com/j2se/1.4.2/docs/...tructor_detail

I think I like your proposal! It seemed reasonable to me to continue to use
the 'jar:file:', since it seems to be acceptable to use
'jar:file:c:\\myJars\\big.jar!/Images/foo.gif' to designate a specific entry
within a jar on the filesystem. After all, a jar on the classpath is also on
the filesystem, by definition. But using a new protocol like your proposed
'classpath:' is clearer than trying to use 'file:' within 'jar:'.

The downside is that no 'classpath:' protocol is known to anyone but you and
me, at least as far as i know. That means it may raise more questions than
it solves if anyone else sees my code. Of course, I could approach whatever
body creates RFCs and suggest the creation of a 'classpath:' protocol but
that strikes me as a process that would drag on for years. Still, that is
probably the best solution from a design point of view....

> >
> > I can't find any discussion of this "special case" in the articles I've
> > seen
> > about the Jar: protocol.
> >

>

Rhino