About jars and accessing stuff inside

P

Philipp

Hello
Inside a jar, how can you get a listing of a folder?

(File.list() does not work)

Thanks Phil
 
P

Philipp

For clarification:
I mean inside the jar which runs the app.

I'm aware of JarFile.entries() but:
1) how to get a reference to the actual running jar file?
2) do I have to parse all entries to choose only the ones in a specific
folder?

Thanks Phil
 
S

Steve W. Jackson

Philipp said:
Hello
Inside a jar, how can you get a listing of a folder?

(File.list() does not work)

Thanks Phil

You need to visit the API documentation and look more closely at how
this works. A JAR file is *not* a "filesystem", so you can't treat its
contents as java.io.File instances. Instead, it's a file itself with
multiple entries. Look at java.util.jar.JarFile and you'll see that it
has methods for iterating over JarEntry items it contains. And you'll
need to remember that a "folder" inside a jar file is yet another entry,
even if the unzipped contents include more files or folders there.

= Steve =
 
P

Philipp

Steve said:
You need to visit the API documentation and look more closely at how
this works. A JAR file is *not* a "filesystem", so you can't treat its
contents as java.io.File instances. Instead, it's a file itself with
multiple entries. Look at java.util.jar.JarFile and you'll see that it
has methods for iterating over JarEntry items it contains. And you'll
need to remember that a "folder" inside a jar file is yet another entry,
even if the unzipped contents include more files or folders there.

Yes I was aware of that. I still have a problem:
- How to get a reference to the actual running jar file?

Phil
 
A

Andrew Thompson

Philipp said:
....
Yes I was aware of that. I still have a problem:
- How to get a reference to the actual running jar file?

Perhaps it is better to investigate why you believe you
need to get a list of files that were (supposedly) put there
by you in the first place.

What is the actual end purpose of this exercise?
What does it bring to the end user?

Andrew T.
 
P

Philipp

Andrew said:
Perhaps it is better to investigate why you believe you
need to get a list of files that were (supposedly) put there
by you in the first place.

What is the actual end purpose of this exercise?
What does it bring to the end user?

OK I have a tool in my application which has some factory presets which
are offered to the user. These presets are written in XML and stored in
the jar at /resources/presets/

Now I don't want to hard code each name of the (many) factory presets. I
just want to specify the folder and the app gets the list of all presets
which are in it.

How should I do this cleanly?

My scenario is also interesting, because the user can build his own
presets and save them somewhere in a folder on his file system (not in
the jar!).
He then just needs to specify once where his home made presets are (ie
the folder name) and the app gets a) the factory presets form the jar b)
the user presets from the filesystem folder, both using the same methods.

Thanks for suggestions
Phil
 
A

Andrew Thompson

Philipp said:
OK I have a tool in my application which has some factory presets which
are offered to the user. These presets are written in XML and stored in
the jar at /resources/presets/

- Use a logical sequence for the file names
(e.g. 1.preset.xml to 299.preset.xml) store the
highest number xml name in a file with a known name.
(e.g. /resources/presets/total.dat).

- Use ant to build the project and write a list of
the xml preset files into a list of known name.

- Extend that to a web-start based (1.5+) launch
with lazy downloads (assuming these files are big),
and test for each (sequentially named) presets file
using the JNLP API.

- Compact the 299 preset files into a single file of
all presets, with a known name.
Now I don't want to hard code each name of the (many) factory presets.

Ant might build a list of them for you, but
there are also other ways to go about it,
as noted above.

.....
How should I do this cleanly?

I am no 'master of design', so I am just kicking a
few ideas about.
My scenario is also interesting, because the user can build his own
presets and save them somewhere in a folder on his file system (not in
the jar!).

The best way to do this is to either
a) Not offer the user a chioice of where to put them,
but to store them in a file in a sub-directory (based
on the reverse package name of your classes, to
avoid name collisions!) of "user.home".
b) Offer the user to choose where to store the presets
(e.g. using a JFileChooser), then store that *location*
as a string in the same place mentioned above
(sub-dir of user.home).

Andrew T.
 
P

Philipp

Andrew said:
- Use a logical sequence for the file names
(e.g. 1.preset.xml to 299.preset.xml) store the
highest number xml name in a file with a known name.
(e.g. /resources/presets/total.dat).

- Use ant to build the project and write a list of
the xml preset files into a list of known name.

- Extend that to a web-start based (1.5+) launch
with lazy downloads (assuming these files are big),
and test for each (sequentially named) presets file
using the JNLP API.

- Compact the 299 preset files into a single file of
all presets, with a known name.

Hello and thank you for your answer.
In fact you are telling me that there is no clean way to do what I want
to do... :-(

I will have to switch to ant building then...

Phil
 
W

wesley.hall

Philipp said:
Hello and thank you for your answer.
In fact you are telling me that there is no clean way to do what I want
to do... :-(

I would say that the way you are trying to do this is not clean
(although, admitedly, some of Andrew's suggestions are not either).

Jar files are not really meant to be 'random access filesystems'.

If you files are XML files, then is there a compelling reason why they
cannot be merged into a single file with multiple <preset> elements (as
per Andrew's last suggestion)? This would be much cleaner, I think.

You can also solve your user defined preset problem by placing a single
XML file in the user's home directory. Your complete list of presets
will then come from the 'master file' inside the jar and the 'user
file' in the user's home directory. This kind of pattern appears in
many places (/etc/profile and ~/.bash_profile for example).
 
P

Philipp

I would say that the way you are trying to do this is not clean
(although, admitedly, some of Andrew's suggestions are not either).

Jar files are not really meant to be 'random access filesystems'.

Yes I see. But I regret that. It would have been easy for Sun to
implement all options File has in a FileInJar class (ie. isDirectory()
exists() list() etc.). The directory structure of a zip is really *very*
close to a real file system.
If you files are XML files, then is there a compelling reason why they
cannot be merged into a single file with multiple <preset> elements (as
per Andrew's last suggestion)? This would be much cleaner, I think.

All in one file is also a possibility (as also suggested by Andrew). But
I like the idea for the user to have separate preset files, so different
users can share their home made presets just by copying the file into a
directory (like for plugins).

I can definitely implement the "1 preset = 1 file" for the user and
"lots presets = 1 file" inside the jar.

My original question was more "can it be done my way" (ie did I miss
something in the docs). The answers is no.
But there are other ways, as suggested, alright.

Phil
 
A

Andrew Thompson

Philipp wrote:
....
My original question was more "can it be done my way" (ie did I miss
something in the docs).

Well. Now that we have discussed some of the alternate
(and perhaps altogether better) strategies*, I can confirm
that it *is* possible to get a list of the contents of a jar
file, then simply enumerate it to find entries of interest.

java.util.jar.JarFile.entries()
java.util.zip.ZipEntry.getName()

* I am not really in a position to judge which is best,
I have used (and abused) most of the methods first listed,
in ways to achieve roughly what you said, but it keeps
coming back to the fundamental question of why the
application jar does not know what it expects to find
inside itself. That factor alone, suggests a potential
design flaw.

Andrew T.
 
P

Philipp

Andrew said:
Philipp wrote:
...

Well. Now that we have discussed some of the alternate
(and perhaps altogether better) strategies*, I can confirm
that it *is* possible to get a list of the contents of a jar
file, then simply enumerate it to find entries of interest.

java.util.jar.JarFile.entries()
java.util.zip.ZipEntry.getName()

Yes you are correct. I tried (hard) to get a workaround using these. I
have come up with some ugly code which I will not share with you as it
too ugly (LOTS of parsing and editing and transforming URLs to URIs to
Strings etc). Probably very brittle as well.
> why the
application jar does not know what it expects to find
inside itself. That factor alone, suggests a potential
design flaw.

Hmmm. I don't think it is a design flaw. It's basic features lacking in
the JAR API (come on! accessing files in an archive... seems pretty
straightforward to me!).
And yes I do know what files are in the jar. So I will fall back to
hardcode the filename as no better / easier solution was offered (or
eventually automate this with ant).

Thanks anyway for your much appreciated help.

Phil
 
S

Steve W. Jackson

Philipp said:
Hello and thank you for your answer.
In fact you are telling me that there is no clean way to do what I want
to do... :-(

I will have to switch to ant building then...

Phil

I don't think he told you that at all...though I may not fully
understand all of what he did tell you.

For accessing things that are in your jar file, you don't need to know
where the jar is. You can access them as "resources". For example, in
my app's jar file I have some images which we use as "icons" of a sort
in a specific package -- call it com.company.icons for simplicity. In
my code, I can access any of them by using the com/company/icons
notation for their location. The same kind of thing can be done for
other kinds of resources -- property files, embedded data files, etc.

For things that are not inside the jar file, assuming you have
appropriate privileges, you can often make a URL or URI referring to
their location (file:// kind of thing) and read them in that way once
you know where they are.

= Steve =
 
P

Philipp

Steve said:
I don't think he told you that at all...though I may not fully
understand all of what he did tell you.

For accessing things that are in your jar file, you don't need to know
where the jar is. You can access them as "resources". For example, in
my app's jar file I have some images which we use as "icons" of a sort
in a specific package -- call it com.company.icons for simplicity. In
my code, I can access any of them by using the com/company/icons
notation for their location. The same kind of thing can be done for
other kinds of resources -- property files, embedded data files, etc.

For things that are not inside the jar file, assuming you have
appropriate privileges, you can often make a URL or URI referring to
their location (file:// kind of thing) and read them in that way once
you know where they are.

Yes I am aware of this. You need to know the exact name of the resource
to use getResource() /getResourceAsStream(). In my case, I would like to
open all files from a folder in the jar (using getResource). But I don't
want to hardcode the name of each file, so I wanted some mechanism to
get the list of the files in a specific folder.
This mechanism does not exist in a straightforward way.

It is possible to:
- get the running JAR name
- by getting the URL to a known dummy resource inside it
- parsing this to get a URL to the jar file (ie take off the dummy
resource path)
- open the jar file (using JarFile)
- list all files in it using entries()
- parse this list to get only the folder you want
- get the resource using getResource

But any suggestion for a better / claener and faster way are welcome.
Phil
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top