Searching inside jar

As part of my work, I often need to find out the jar archive that contains a particular class files. The product that I work has quite large number of archive files. Finding the class file manually on each jar archive will be a hectic job.  

This made me to write an automated procedure, that does the task. This motive ended up in a shell script. Though it satisfies my purpose, some of colleagues badly need the same task to be done in Windows too. Though I am “aware” of java and know that it could solve the purpose, I strongly feel that java is not the language for the above problem. The next thing that strikes my mind is “Perl”. I am not exposed to Perl before (I haven’t tried even a single solution using Perl). After a bit of learning, started to write script that solves the above problem. After striving for nearly 4 hours I came out with the solution that solved the purpose both in Windows and *Nix system. I don’t have a MAC system, if anybody finds a problem with Mac (or even with NT or *Nix) systems kindly let me know.

 

# Author: Veerabahu Subramanian C <veechand@gmail.com>
#
# This software is distributed AS-IS.  The author offers no warranty or
# guarantee.  Best effort email support may be provided solely by the author
# listed above.</pre>
#Multi-line comment: use Acme::Comment type=>'java', own_line=>1;
#ClassFileName - ARGV[0]
#Directory to search, this is optional i will use currect directory - ARGV[1]
#Both of this can be a regex

use strict;
use warnings;
use Cwd;

use File::Find;
use File::Basename;

my ( $class_name, $dir_name );

#only class name is given so by default taking the current directory
if ( scalar(@ARGV) == 1 ) {
 ( $class_name, $dir_name ) = ( $ARGV[0], cwd );
}

#both classname and directory to search is given
elsif ( scalar(@ARGV) == 2 ) {
 ( $class_name, $dir_name ) = ( $ARGV[0], $ARGV[1] );
}
else {
 print "USAGE: perl finjar.pl <filename to find inside jarfile> [<location>] \n" .
 "*) Current directory will be the default location \n" .
 "*) Both the parameters can be regular expression \n" .
 "*) Both the parameters are taken in case in-sensitive manner \n" .
 "*) Quote spaces in parameter \n" ;
 exit;
}
if (index ($^O,"Win") != -1){
 $dir_name =~ s,/,\\,g;
}
find( \&processfiles, $dir_name );

sub processfiles {
 my $file = $File::Find::name;    #this will give the complete path
 my @pacakge_structure;
 my $current_class_name;
 if (index ($^O,"Win") != -1){
 $file =~ s,/,\\,g;
 }
 return unless -f $file;            #process only files
 return unless $_ =~ m/\.jar/io;    #process only jar file
 $file = "\"" . $file . "\"";
 my @jarcontents;
 if ( index( $^O, "Win" ) != -1 ) {
    @jarcontents = `jar -tf $file`;
 }
 else {
    @jarcontents = `unzip -l $file`;
 }
 my $jarcontains = 0;                 #false
 for my $content (@jarcontents) {

 #I am trying to take only the class name and compare
 #the value of _contents will be something like a/b/c/XYZ.class
 #I am trying to take XYZ out and compare that with file pattern
 @pacakge_structure = split( /\//, $content );
 $current_class_name = $pacakge_structure[$#pacakge_structure];
 if ( $current_class_name  =~ m/$class_name/io ) {
 print $content . "\n";
 $jarcontains = 1;                               #setting to true
 }
 }
 if ( $jarcontains == 1 ) {
 print $file . "\n";
 }

}

 

You can run the script by keying “perl findjar.pl <filename to find inside jarfile> [<location>]“, provided

1.       Copied the above code and saved as findjar.pl

2.       Perl and jar(for windows)/unzip(for solaris) executable are in classpath

Also, my sincere thanks to Rene Nyffenegger and Christopher Hilding who gave me confidence that the above problem (finding within jar) can be solved in Perl.

Spare a minute for your valuable comments (coding or general)

Updates:  Thanks, for all those who have taken time to evaluate and write your comments. Special thanks to Claudio Miranda for your excellent comment. I have updated the tool now. But I made a specific check to use unzip only if it is in *nix systems. I hope that holds good. Any comments?

Advertisements

5 Responses

  1. The tool will certainly help developers, particularly for developers who work in a big products.

    I have also written a similar tool in Java with SWING user interface.

  2. Veeru… Good tool and much improved version from the legacy findjar.sh 🙂

    Cheers!!!

  3. Nice script, however I did a small modification that helped a lot
    Change the ” jar tf ” command to ” unzip -l “,
    Tested with the following search perl findjar.pl Constants /opt/netbeans-6.5/
    The time decreased from 5min12s to 8s. Very good.
    I wrote a similar script (bash) some time ago (portuguese blog http://www.claudius.com.br/blog/claudio/2007/07/30/Como-encontrar-uma-classe)
    cheers.

  4. Would it be possible to enhance this script for finding the class in a zip file also ?? My application contains a zip file which contains lot of classes 🙂 …

    Regards
    Prathib Kumar.

  5. Or even left this option to the user, so that this script could be used for any extensions

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: