How to find a .class file in a bunch of JARs?

L

laredotornado

Hi,

I'm on Solaris 9. Does anyone know of a way to search through JAR
files (all of which are in the same directory) to find a class
"my.class" without having to unzip each file?

Thanks, - Dave
 
O

Owen Jacobson

Hi,

I'm on Solaris 9.  Does anyone know of a way to search through JAR
files (all of which are in the same directory) to find a class
"my.class" without having to unzip each file?

Thanks, - Dave

grep -l foo/bar/my.class *.jar

-o
 
K

Knute Johnson

laredotornado said:
Hi,

I'm on Solaris 9. Does anyone know of a way to search through JAR
files (all of which are in the same directory) to find a class
"my.class" without having to unzip each file?

Thanks, - Dave

See the docs for the JarFile class.
 
M

Mike Schilling

laredotornado said:
Hi,

I'm on Solaris 9. Does anyone know of a way to search through JAR
files (all of which are in the same directory) to find a class
"my.class" without having to unzip each file?

I have a script I use for just that:

#! /bin/tcsh
foreach file ( $1/*jar )
echo $file
jar tf $file | grep $2
end
 
A

Abhijat Vatsyayan

laredotornado said:
Hi,

I'm on Solaris 9. Does anyone know of a way to search through JAR
files (all of which are in the same directory) to find a class
"my.class" without having to unzip each file?

Thanks, - Dave
While on unix I will almost always use the shell, here is a quick and
dirty java based approach -

package net.abhijat.news.cl;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.StringTokenizer;

public class ResourceFinder
{
private File dir ;
private ClassLoader classLoader ;
ResourceFinder(String dir) throws MalformedURLException
{
this.dir = new File(dir);
initSelf() ;
}
private void initSelf() throws MalformedURLException
{
FileFilter fileFilter = new filter();
File[] jarFiles = dir.listFiles(fileFilter);
URL[] jarURLs = new URL[jarFiles.length];
for (int i = 0; i < jarFiles.length; i++)
{
File jarFile = jarFiles;
jarURLs = jarFile.toURL();
}
classLoader = new URLClassLoader(jarURLs, null);
}
public Collection<String> getJarsContainingClass(String fqClassname)
throws IOException
{
String resName = fqClassname.replace('.', '/')+".class";
Collection<String> jarFiles = new LinkedList<String>();
Enumeration<URL> urls = classLoader.getResources(resName);
while (urls.hasMoreElements())
{
URL url = urls.nextElement();
jarFiles.add(stringForm(url));
}
return jarFiles;
}
private static String stringForm(URL jarURL)
{
String jarPath = jarURL.toExternalForm();
StringTokenizer st = new StringTokenizer(jarPath, "!");
return st.nextToken();
}
class filter implements FileFilter
{
public boolean accept(File pathname)
{
if(pathname.isDirectory())
{
return false;
}
return pathname.getName().endsWith(".jar");
}
}
/**
* args[0] is the directory containing jars , args[1] is the fully
qualified classname
* @param args
*/
public static void main(String[] args)
{
try
{
String dir = args[0];
String clsName = args[1];
ResourceFinder finder = new ResourceFinder(dir);
Collection<String> urls = finder.getJarsContainingClass(clsName);
for (String url : urls)
{
System.out.println("[ResourceFinder::main()] "+url);
}
System.exit(0);
}
catch(Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
}
 
A

Alex.From.Ohio.Java

laredotornado said:
I'm on Solaris 9. Does anyone know of a way to search through JAR
files (all of which are in the same directory) to find a class
"my.class" without having to unzip each file?
Thanks, - Dave

While on unix I will almost always use the shell, here is a quick and
dirty java based approach -

package net.abhijat.news.cl;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.StringTokenizer;

public class ResourceFinder
{
private File dir ;
private ClassLoader classLoader ;
ResourceFinder(String dir) throws MalformedURLException
{
this.dir = new File(dir);
initSelf() ;
}
private void initSelf() throws MalformedURLException
{
FileFilter fileFilter = new filter();
File[] jarFiles = dir.listFiles(fileFilter);
URL[] jarURLs = new URL[jarFiles.length];
for (int i = 0; i < jarFiles.length; i++)
{
File jarFile = jarFiles;
jarURLs = jarFile.toURL();
}
classLoader = new URLClassLoader(jarURLs, null);
}
public Collection<String> getJarsContainingClass(String fqClassname)
throws IOException
{
String resName = fqClassname.replace('.', '/')+".class";
Collection<String> jarFiles = new LinkedList<String>();
Enumeration<URL> urls = classLoader.getResources(resName);
while (urls.hasMoreElements())
{
URL url = urls.nextElement();
jarFiles.add(stringForm(url));
}
return jarFiles;
}
private static String stringForm(URL jarURL)
{
String jarPath = jarURL.toExternalForm();
StringTokenizer st = new StringTokenizer(jarPath, "!");
return st.nextToken();
}
class filter implements FileFilter
{
public boolean accept(File pathname)
{
if(pathname.isDirectory())
{
return false;
}
return pathname.getName().endsWith(".jar");
}
}
/**
* args[0] is the directory containing jars , args[1] is the fully
qualified classname
* @param args
*/
public static void main(String[] args)
{
try
{
String dir = args[0];
String clsName = args[1];
ResourceFinder finder = new ResourceFinder(dir);
Collection<String> urls = finder.getJarsContainingClass(clsName);
for (String url : urls)
{
System.out.println("[ResourceFinder::main()] "+url);
}
System.exit(0);
}
catch(Exception e)
{
e.printStackTrace();
System.exit(1);
}
}

}


I like JWhich better.

http://groups.google.com/group/comp...52c6b?hl=en&lnk=gst&q=jwhich#51e2bcbc8d652c6b

Sure, you can say it should be in classpath. But that's the point. You
may have dozens of jars with the same class and you want to know which
one exactly you are using inside your Java environment.

Alex.
http://www.myjavaserver.com/~alexfromohio/
 
A

Abhijat Vatsyayan

laredotornado said:
Hi,
I'm on Solaris 9. Does anyone know of a way to search through JAR
files (all of which are in the same directory) to find a class
"my.class" without having to unzip each file?
Thanks, - Dave
While on unix I will almost always use the shell, here is a quick and
dirty java based approach -

package net.abhijat.news.cl;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.StringTokenizer;

public class ResourceFinder
{
private File dir ;
private ClassLoader classLoader ;
ResourceFinder(String dir) throws MalformedURLException
{
this.dir = new File(dir);
initSelf() ;
}
private void initSelf() throws MalformedURLException
{
FileFilter fileFilter = new filter();
File[] jarFiles = dir.listFiles(fileFilter);
URL[] jarURLs = new URL[jarFiles.length];
for (int i = 0; i < jarFiles.length; i++)
{
File jarFile = jarFiles;
jarURLs = jarFile.toURL();
}
classLoader = new URLClassLoader(jarURLs, null);
}
public Collection<String> getJarsContainingClass(String fqClassname)
throws IOException
{
String resName = fqClassname.replace('.', '/')+".class";
Collection<String> jarFiles = new LinkedList<String>();
Enumeration<URL> urls = classLoader.getResources(resName);
while (urls.hasMoreElements())
{
URL url = urls.nextElement();
jarFiles.add(stringForm(url));
}
return jarFiles;
}
private static String stringForm(URL jarURL)
{
String jarPath = jarURL.toExternalForm();
StringTokenizer st = new StringTokenizer(jarPath, "!");
return st.nextToken();
}
class filter implements FileFilter
{
public boolean accept(File pathname)
{
if(pathname.isDirectory())
{
return false;
}
return pathname.getName().endsWith(".jar");
}
}
/**
* args[0] is the directory containing jars , args[1] is the fully
qualified classname
* @param args
*/
public static void main(String[] args)
{
try
{
String dir = args[0];
String clsName = args[1];
ResourceFinder finder = new ResourceFinder(dir);
Collection<String> urls = finder.getJarsContainingClass(clsName);
for (String url : urls)
{
System.out.println("[ResourceFinder::main()] "+url);
}
System.exit(0);
}
catch(Exception e)
{
e.printStackTrace();
System.exit(1);
}
}

}


I like JWhich better.

http://groups.google.com/group/comp...52c6b?hl=en&lnk=gst&q=jwhich#51e2bcbc8d652c6b

Sure, you can say it should be in classpath. But that's the point. You
may have dozens of jars with the same class and you want to know which
one exactly you are using inside your Java environment.

Alex.
http://www.myjavaserver.com/~alexfromohio/

I assumed that the class was not in the classpath. Think of this as a
lazy way to read jars file contents which replaces the unix shell
scripts (not that there is any reason to :) ).

Moreover, I don't think the original post said anything about figuring
out which specific class file (from which URL/jar/dir) was being used in
a context. Figuring that out is just as simple.

Abhijat
 
G

Gordon Beaton

I'm on Solaris 9. Does anyone know of a way to search through JAR
files (all of which are in the same directory) to find a class
"my.class" without having to unzip each file?

for j in *.jar ; do
if jar tf $j | grep -q My.class ; then
echo found My.class in $j
fi
done

/gordon

--
 
L

laredotornado

grep -l foo/bar/my.class *.jar

-o

I like the one-lineness of this solution, but when I try it, I'm
getting no results. Maybe I'm doing something wrong. In a JAR file,
I have the class com.myco.nps.im.gui.utils.NPSIMPropertiesMgr.class
but when I execute the command from within my WEB-INF/lib directory

grep -l com/myco/nps/im/gui/utils/NPSIMPropertiesMgr.class *.jar

I get nothing. Am I doing something wrong with the above? -
 
N

Nigel Wade

laredotornado said:
I like the one-lineness of this solution, but when I try it, I'm
getting no results. Maybe I'm doing something wrong. In a JAR file,
I have the class com.myco.nps.im.gui.utils.NPSIMPropertiesMgr.class
but when I execute the command from within my WEB-INF/lib directory

grep -l com/myco/nps/im/gui/utils/NPSIMPropertiesMgr.class *.jar

I get nothing. Am I doing something wrong with the above? -

grep on Solaris [2.7] doesn't like binary files. Also jar -t on Solaris doesn't
do what it's supposed to and outputs the table of contents to stderr rather
than stdout so you can't do a simple redirect of jar tf | grep. You'd think Sun
could get this right on their own OS wouldn't you?

Instead of grep try egrep.

If you want to use the loop method on the jar table of contents you have to use
a different incantation of the pipe:

for jar in *.jar ; do
jar tf $jar 2>&1 | grep whatever
done
 
J

John B. Matthews

Nigel Wade said:
laredotornado said:
I like the one-lineness of this solution, but when I try it, I'm
getting no results. Maybe I'm doing something wrong. In a JAR file,
I have the class com.myco.nps.im.gui.utils.NPSIMPropertiesMgr.class
but when I execute the command from within my WEB-INF/lib directory

grep -l com/myco/nps/im/gui/utils/NPSIMPropertiesMgr.class *.jar

I get nothing. Am I doing something wrong with the above? -

grep on Solaris [2.7] doesn't like binary files. Also jar -t on
Solaris doesn't do what it's supposed to and outputs the table of
contents to stderr rather than stdout so you can't do a simple
redirect of jar tf | grep. You'd think Sun could get this right on
their own OS wouldn't you?

Instead of grep try egrep.

If you want to use the loop method on the jar table of contents you
have to use a different incantation of the pipe:

for jar in *.jar ; do
jar tf $jar 2>&1 | grep whatever
done

Delightful! When the jars are scattered about:

find $JAVA_HOME/lib -name \*jar -exec jar tf {} \; 2>&1 | grep whatever
 
M

Mark Space

John said:
find $JAVA_HOME/lib -name \*jar -exec jar tf {} \; 2>&1 | grep whatever

Nice! The find command is awesome and often overlooked. On my system
however this doesn't print the names of files, just the names of the
class you looked for. This is a bit sneakier:

find <path> -name \*jar -exec strings -f {} \; grep search_string

This will also print a line if the path name matches too... maybe look
for characters following a : ...


find <path> -name \*jar -exec strings -f {} \; egrep :.+search_string
 
J

John B. Matthews

Mark Space said:
Nice! The find command is awesome and often overlooked. On my system
however this doesn't print the names of files, just the names of the
class you looked for. This is a bit sneakier:

find <path> -name \*jar -exec strings -f {} \; grep search_string

This will also print a line if the path name matches too... maybe look
for characters following a : ...

find <path> -name \*jar -exec strings -f {} \; egrep :.+search_string

Kewl, er, I mean exemplary! My strings doesn't have -f, but xargs will
echo the path name with -t:

find <path> -name \*jar -print0 | xargs -t jar tf | grep ...

No pipe required between "{} \;" and "grep"?
 
O

Owen Jacobson

I like the one-lineness of this solution, but when I try it, I'm
getting no results.  Maybe I'm doing something wrong.  In a JAR file,
I have the class com.myco.nps.im.gui.utils.NPSIMPropertiesMgr.class
but when I execute the command from within my WEB-INF/lib directory
grep -l com/myco/nps/im/gui/utils/NPSIMPropertiesMgr.class *.jar
I get nothing.  Am I doing something wrong with the above? -

grep on Solaris [2.7] doesn't like binary files.

I learn something new every day.

The approach I use has always served me well on OS X (BSD) and Linux,
so it's doubly surprising that Solaris grep doesn't handle it.

-o
 
N

Nigel Wade

Owen said:
laredotornado said:
I'm on Solaris 9.  Does anyone know of a way to search through JAR
files (all of which are in the same directory) to find a class
"my.class" without having to unzip each file?
Thanks, - Dave
grep -l foo/bar/my.class *.jar

I like the one-lineness of this solution, but when I try it, I'm
getting no results.  Maybe I'm doing something wrong.  In a JAR file,
I have the class com.myco.nps.im.gui.utils.NPSIMPropertiesMgr.class
but when I execute the command from within my WEB-INF/lib directory
grep -l com/myco/nps/im/gui/utils/NPSIMPropertiesMgr.class *.jar
I get nothing.  Am I doing something wrong with the above? -

grep on Solaris [2.7] doesn't like binary files.

I learn something new every day.

The approach I use has always served me well on OS X (BSD) and Linux,
so it's doubly surprising that Solaris grep doesn't handle it.

SunOS/Solaris is an old OS, with a long tradition of backwards compatibility.

Many of the traditional UNIX tools date back decades, and their behaviour is
entrenched so as not to break existing code. In Solaris the default application
will be the traditional one. There may be others which conform to later
standards (for example Solaris 2.7 includes an XPG4 version of grep). A later
version of grep, egrep, was introduced which incorporates many additions (most
notably use of "extended" regular expressions, hence the name). egrep seems to
handle binary files much better.

The newer OS, such as Linux, don't have the tradition or necessity of backward
compatibility and hence use egrep as grep. I'm surprised that BSD has
supplanted grep with egrep, or maybe that is just an Appleism - they are not
exactly noted for backward compatibility in anything.
 
M

maaxiim

Kewl, er, I mean exemplary! My strings doesn't have -f, but xargs will
echo the path name with -t:

find <path> -name \*jar -print0 | xargs -t jar tf | grep ...
<pedantic>
'find' is definitely a must in the programmer toolbox, but there's a
little gotcha that I wanted to bring up here;

It's generally better to use the

{grep <pattern> `find <path> -name <filename-pattern> -print`}

than

{find <path> -name <filename-pattern> -exec grep \{} \; -print}

for the simple reason that the first form will execute the grep once
for the generated list of names
matched by find, whereas the second form will launch a new instance of
grep for every file, which
can become quite resource-unfriendly if you're executing a search
across a large file-set or over
the network, etc. Of course, the syntax for breaking up large file-
lists using xargs is not so intuitive
either, but I guess thats just the price you pay.
</pedantic>
 
L

laredotornado

laredotornadowrote:
I like the one-lineness of this solution, but when I try it, I'm
getting no results.  Maybe I'm doing something wrong.  In a JAR file,
I have the class com.myco.nps.im.gui.utils.NPSIMPropertiesMgr.class
but when I execute the command from within my WEB-INF/lib directory
grep -l com/myco/nps/im/gui/utils/NPSIMPropertiesMgr.class *.jar
I get nothing.  Am I doing something wrong with the above? -

grep on Solaris [2.7] doesn't like binary files. Also jar -t on Solaris doesn't
do what it's supposed to and outputs the table of contents to stderr rather
than stdout so you can't do a simple redirect of jar tf | grep. You'd think Sun
could get this right on their own OS wouldn't you?

Instead of grep try egrep.

If you want to use the loop method on the jar table of contents you have to use
a different incantation of the pipe:

for jar in *.jar ; do
  jar tf $jar 2>&1 | grep whatever
done

Thanks. When I changed to egrep, it found the classes.
 

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,787
Messages
2,569,631
Members
45,338
Latest member
41Pearline46

Latest Threads

Top