how to read file list from nested jar/war/ear

B

boku

Guys

I'm trying to write a utilty that can search class name from jar/war/ear.
Sometime, I see an ear file that has several war files which has some jars in
it. I thougth I could write a recurive function, but I don't know how to get the
list from the nested jar.

Any suggestion?

Here is the part of function I'm writing.

public static void findInArchive(String searchingString, File archiveName) {

FileInputStream fis = new FileInputStream(archiveName);
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));

ZipEntry entry = null;
String pathName, fileName;

while ((entry = zis.getNextEntry()) != null) {
pathName = entry.getName();
fileName = pathName.substring(pathName.lastIndexOf('/')+1);

if (pathName.endsWith(".jar") || pathName.endsWith(".zip") ||
pathName.endsWith(".war") || pathName.endsWith(".ear")) {
findInArchive(); // Not sure what to do here
}

// search for the matching string on the list of archive...
}
}
 
R

Roedy Green

I thougth I could write a recurive function, but I don't know how to get the
list from the nested jar.

You have to extract that either to a byte array stream or hard disk,
then process it further recursively.
 
T

Thomas Weidenfeller

boku said:
I'm trying to write a utilty that can search class name from jar/war/ear.
Sometime, I see an ear file that has several war files which has some jars in
it. I thougth I could write a recurive function, but I don't know how to get the
list from the nested jar.

The zip/jar API is rather ugly (e.g. ZipFile and ZipInputStream have a
similar but incompatible API). In fact, Sun had to use a sledge hammer
to wrap the C library they use into something that almost fits into the
Java I/O system.

I recently had a go at it when writing a self-extracting jar /
installer tool for fun. It wasn't too much fun :-(
Any suggestion?

Here is a rough sketch of what might work. Note that I use a different,
more OO-like class, and not static methods. I didn't run the code
through a compiler, I omitted all exception handling, etc.:

public class ArchiveEntryFinder {
protected File archive;

public ArchiveEntryFinder(File archive) {
this.archive = archive;
}

public ArchiveEntryFinder(String archive) {
this(new File(archive));
}

public InputStream find(String name) {
//
// Forget about ZipFile in this case. It is fast, but
// can't work on an InputStream. And every entry you get
// an entry out of a zip file is always an InputStream.
//
ZipInputStream root = new BufferedInputStream(
new FileInputStream(archive);
);

return find(root, name); // enter the recursion
}

public boolean isArchive(String name) {
// @todo use a more intelligent test to identify a
// zip-based archive (magic number?)
String s = name.toLowerCase();
return s.endsWith(".jar")
|| s.endsWith(".war")
|| s.endsWith(".zip")
|| s.endsWith(".ear");
}


protected InputStream find(ZipInputStream in, name) {

//
// note: getNextEntry()'s behavior regarding no more
// entries is undocumented...
//
ZipEntry entry;
while((entry = in.getNextEntry()) != null) {
String entryName = entry.getName();

if(entryName.endsWith(name)) {
//
// Hack: Zip file is correctly positioned,
// return it as input stream. Rely on
// a correct override of read(byte[], int, int)
// in ZipInputStream.
//
return in;
}

if(isArchive(entryName)) {
//
// Wrap current ZipInputStream entry into
// a new ZipInputStream.
// No need to use a BufferedInputStream in
// addition, since the original one is still
// somewhere present in this mess.
//
InputStream result = find(
new ZipInputStream(in),
name
);
if(result != null) {
return result;
}
}
in.closeEntry();
}
return null; // nothing found
}

}


HTH

/Thomas
 
B

boku

Thanks for the suggestion. I'll try that.

boku said:
I'm trying to write a utilty that can search class name from jar/war/ear.
Sometime, I see an ear file that has several war files which has some jars in
it. I thougth I could write a recurive function, but I don't know how to get the
list from the nested jar.

The zip/jar API is rather ugly (e.g. ZipFile and ZipInputStream have a
similar but incompatible API). In fact, Sun had to use a sledge hammer
to wrap the C library they use into something that almost fits into the
Java I/O system.

I recently had a go at it when writing a self-extracting jar /
installer tool for fun. It wasn't too much fun :-(
Any suggestion?

Here is a rough sketch of what might work. Note that I use a different,
more OO-like class, and not static methods. I didn't run the code
through a compiler, I omitted all exception handling, etc.:

public class ArchiveEntryFinder {
protected File archive;

public ArchiveEntryFinder(File archive) {
this.archive = archive;
}

public ArchiveEntryFinder(String archive) {
this(new File(archive));
}

public InputStream find(String name) {
//
// Forget about ZipFile in this case. It is fast, but
// can't work on an InputStream. And every entry you get
// an entry out of a zip file is always an InputStream.
//
ZipInputStream root = new BufferedInputStream(
new FileInputStream(archive);
);

return find(root, name); // enter the recursion
}

public boolean isArchive(String name) {
// @todo use a more intelligent test to identify a
// zip-based archive (magic number?)
String s = name.toLowerCase();
return s.endsWith(".jar")
|| s.endsWith(".war")
|| s.endsWith(".zip")
|| s.endsWith(".ear");
}


protected InputStream find(ZipInputStream in, name) {

//
// note: getNextEntry()'s behavior regarding no more
// entries is undocumented...
//
ZipEntry entry;
while((entry = in.getNextEntry()) != null) {
String entryName = entry.getName();

if(entryName.endsWith(name)) {
//
// Hack: Zip file is correctly positioned,
// return it as input stream. Rely on
// a correct override of read(byte[], int, int)
// in ZipInputStream.
//
return in;
}

if(isArchive(entryName)) {
//
// Wrap current ZipInputStream entry into
// a new ZipInputStream.
// No need to use a BufferedInputStream in
// addition, since the original one is still
// somewhere present in this mess.
//
InputStream result = find(
new ZipInputStream(in),
name
);
if(result != null) {
return result;
}
}
in.closeEntry();
}
return null; // nothing found
}

}


HTH

/Thomas
 
Joined
Nov 10, 2008
Messages
2
Reaction score
0
New tool is available

The new tool "Search for files inside compressed archives" of DJ Java Decompiler enables users to search inside compressed .JAR, .ZIP, .APK, .WAR, .EAR and .EXE archives:
neshkov .com
It's possible to search for files by file name and a word or phrase in the compressed (zipped) file.
 

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

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,241
Members
46,831
Latest member
RusselWill

Latest Threads

Top