annotate javadoc-search.pl @ 0:0d795f02a8bb tip

initial committ. what was I thinking?
author Robert McIntyre <rlm@mit.edu>
date Mon, 27 Sep 2010 16:57:26 -0400
parents
children
rev   line source
rlm@0 1 #!/usr/bin/perl
rlm@0 2
rlm@0 3 use strict;
rlm@0 4 use vars qw / $javadocRoots $indexFile $resultFrame $linkFrame $gzip /;
rlm@0 5 #####################################################################
rlm@0 6 #
rlm@0 7 # javadoc-search
rlm@0 8 #
rlm@0 9 # http://sourceforge.net/projects/javadoc-search/
rlm@0 10 #
rlm@0 11 # Copyright (C) 2002-2003, Nicholas Sushkin.
rlm@0 12 #
rlm@0 13 # This program is free software; you can redistribute it and/or modify
rlm@0 14 # it under the terms of the GNU General Public License as published by
rlm@0 15 # the Free Software Foundation; either version 2 of the License, or
rlm@0 16 # (at your option) any later version.
rlm@0 17 #
rlm@0 18 # This program is distributed in the hope that it will be useful,
rlm@0 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
rlm@0 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
rlm@0 21 # GNU General Public License for more details.
rlm@0 22 #
rlm@0 23 # You should have received a copy of the GNU General Public License
rlm@0 24 # along with this program; if not, write to the Free Software
rlm@0 25 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
rlm@0 26 #
rlm@0 27 #
rlm@0 28 # Instructions are at http://javadoc-search.sourceforge.net/
rlm@0 29 #
rlm@0 30 #
rlm@0 31 #####################################################################
rlm@0 32 #
rlm@0 33 # $Id: javadoc-search.pl,v 1.8 2003/08/19 00:11:09 nsushkin Exp $
rlm@0 34 #
rlm@0 35 #####################################################################
rlm@0 36
rlm@0 37 ### Indexing setup
rlm@0 38
rlm@0 39 # list of subdirectories of docroot to search for javadoc index files
rlm@0 40 # Windows and Apache - prefix with drive letter and use only lowercase letters.
rlm@0 41 # $javadocRoots = [ "c:/program\ files/apache/htdocs/docs" ];
rlm@0 42 # Unix
rlm@0 43 # $javadocRoots = [ "/usr/local/apache/htdocs/docs" ];
rlm@0 44 $javadocRoots = [ "/usr/local/apache/htdocs/docs" ];
rlm@0 45
rlm@0 46 # index file, if ends with .gz will use gzip
rlm@0 47 # Windows
rlm@0 48 # $indexFile = "c:/bin/apache\ group/apache/javadoc-index.txt";
rlm@0 49 # Unix
rlm@0 50 # $indexFile = "/usr/local/apache/htdocs/docs/javadoc-index.txt.gz";
rlm@0 51 $indexFile = "/usr/local/apache/htdocs/docs/javadoc-index.txt.gz";
rlm@0 52
rlm@0 53 ### Display style setup
rlm@0 54
rlm@0 55 # if $resultFrame is not empty, display search results in this frame
rlm@0 56 $resultFrame = "";
rlm@0 57
rlm@0 58 # if $linkFrame is not empty, open javadoc links in this frame
rlm@0 59 $linkFrame = "";
rlm@0 60
rlm@0 61 ### Auxillary programs setup
rlm@0 62
rlm@0 63 # which gzip
rlm@0 64 $gzip = "/usr/bin/gzip";
rlm@0 65
rlm@0 66 # nothing below is customizable
rlm@0 67 #####################################################################
rlm@0 68 use Getopt::Std;
rlm@0 69 use File::Find;
rlm@0 70
rlm@0 71 my @indexFiles;
rlm@0 72 my %links;
rlm@0 73
rlm@0 74 (my $rev = '$Revision: 1.8 $') =~ s/^\$\w+: ([\.\d]+) \$$/$1/;
rlm@0 75
rlm@0 76 sub usage
rlm@0 77 {
rlm@0 78 print STDERR <<EOUSAGE;
rlm@0 79 Javadoc Search $rev
rlm@0 80
rlm@0 81 Usage: $0 [-h] [-r]
rlm@0 82
rlm@0 83 -h prints this help
rlm@0 84 -r builds index
rlm@0 85
rlm@0 86 This is a cgi script to search javadoc for classes, members, and methods
rlm@0 87 using an index.
rlm@0 88 EOUSAGE
rlm@0 89
rlm@0 90 }
rlm@0 91
rlm@0 92 #
rlm@0 93 # Build index part
rlm@0 94 #
rlm@0 95 sub indexWrite
rlm@0 96 {
rlm@0 97 print STDERR "Writing all ", indexGetLinkCount(), " links to $indexFile .. ";
rlm@0 98
rlm@0 99 if ($indexFile =~ /\.gz$/)
rlm@0 100 {
rlm@0 101 open(OUTPUT, "| $gzip -c > \"$indexFile\"") || die "unable to gzip to $indexFile: $!\n";
rlm@0 102 }
rlm@0 103 else
rlm@0 104 {
rlm@0 105 open(OUTPUT, ">" . $indexFile) || die "unable to write to $indexFile: $!\n";
rlm@0 106 }
rlm@0 107
rlm@0 108 my $oldSearchKey = "";
rlm@0 109 foreach (sort { $links{$a} cmp $links{$b} } keys %links)
rlm@0 110 {
rlm@0 111 my $searchKey = $links{$_};
rlm@0 112 if ($searchKey ne $oldSearchKey)
rlm@0 113 {
rlm@0 114 if ($oldSearchKey ne "") { print OUTPUT "\n"; }
rlm@0 115 print OUTPUT $searchKey;
rlm@0 116 }
rlm@0 117 print OUTPUT "\t", $_;
rlm@0 118
rlm@0 119 $oldSearchKey = $searchKey;
rlm@0 120 }
rlm@0 121 print OUTPUT "\n";
rlm@0 122
rlm@0 123 close(OUTPUT);
rlm@0 124
rlm@0 125 print STDERR "done\n";
rlm@0 126 }
rlm@0 127
rlm@0 128 sub indexGetLinkCount
rlm@0 129 {
rlm@0 130 scalar(keys %links);
rlm@0 131 }
rlm@0 132
rlm@0 133 sub indexRebuild
rlm@0 134 {
rlm@0 135 find(\&indexFileFinder, @$javadocRoots);
rlm@0 136
rlm@0 137 foreach (@indexFiles)
rlm@0 138 {
rlm@0 139 parseLinks($$_[0], $$_[1]);
rlm@0 140 }
rlm@0 141 }
rlm@0 142
rlm@0 143 sub indexFileFinder
rlm@0 144 {
rlm@0 145 return unless -f $File::Find::name;
rlm@0 146 return unless /^index-.*html??/;
rlm@0 147
rlm@0 148 push @indexFiles, [$File::Find::name, $File::Find::dir];
rlm@0 149 }
rlm@0 150
rlm@0 151 sub indexAddLink
rlm@0 152 {
rlm@0 153 my $key = shift;
rlm@0 154 my $link = shift;
rlm@0 155
rlm@0 156 $links{$link} = $key;
rlm@0 157 }
rlm@0 158
rlm@0 159 sub parseLinks()
rlm@0 160 {
rlm@0 161 my $fileName = shift;
rlm@0 162 my $dirName = shift;
rlm@0 163
rlm@0 164 print STDERR "Parsing ", $fileName, ": ";
rlm@0 165
rlm@0 166 open(FILE, $fileName);
rlm@0 167
rlm@0 168 while(<FILE>)
rlm@0 169 {
rlm@0 170 if($_ =~ m/<A[^>]+?HREF\s*=\s*[\"\']?([^\'\" >]+?)[ \'\"]?(>| title=)/sig)
rlm@0 171 {
rlm@0 172 parseLink($1, $dirName);
rlm@0 173 }
rlm@0 174 }
rlm@0 175
rlm@0 176 close(FILE);
rlm@0 177
rlm@0 178 print STDERR indexGetLinkCount(), " links\n";
rlm@0 179 }
rlm@0 180
rlm@0 181 sub parseLink()
rlm@0 182 {
rlm@0 183 my $link = shift;
rlm@0 184 my $dirName = shift;
rlm@0 185
rlm@0 186 return if $link =~ qr'^(http|ftp)://'i;
rlm@0 187
rlm@0 188 # print "# link=", $link, "\n";
rlm@0 189
rlm@0 190 my $abslink = ( $link =~ qr'^[\./]*([^\./].*)' ) ? $1 : $link;
rlm@0 191 # print "# abslink= $abslink\n";
rlm@0 192
rlm@0 193 return unless $abslink =~ qr'/';
rlm@0 194
rlm@0 195 my ($file,$anchor) = split '#', $abslink;
rlm@0 196 # print "# file=$file, anchor=$anchor\n";
rlm@0 197
rlm@0 198 my $class = ($file =~ /(.*)\.html??/ ) ? $1 : return;
rlm@0 199 $class =~ tr{\/}{\.};
rlm@0 200
rlm@0 201 # print "# class=", $class, "\n";
rlm@0 202 # print "# dirname=", $dirName, "\n";
rlm@0 203
rlm@0 204 # cancel out ".."
rlm@0 205 if ($link =~ /^\.\.\//)
rlm@0 206 {
rlm@0 207 my @linkSegs = split '/', $link;
rlm@0 208 my @dirSegs = split '/', $dirName;
rlm@0 209
rlm@0 210 while (@linkSegs[0] eq '..' and $#dirSegs >= 0)
rlm@0 211 {
rlm@0 212 shift @linkSegs;
rlm@0 213 pop @dirSegs;
rlm@0 214 }
rlm@0 215 $link = join '/', @linkSegs;
rlm@0 216 $dirName = join '/', @dirSegs;
rlm@0 217 }
rlm@0 218 my $fullLink = ( $link =~ /^\// ) ? $link : $dirName . "/" . $link;
rlm@0 219
rlm@0 220 my $key = $anchor eq "" ? $class : $class . '#' . $anchor;
rlm@0 221 indexAddLink($key, $fullLink);
rlm@0 222 }
rlm@0 223
rlm@0 224 #
rlm@0 225 # CGI part
rlm@0 226 #
rlm@0 227 use CGI qw(:standard);
rlm@0 228
rlm@0 229 my $searchTypes = {'c'=>'class','cm'=>'class#member','cma'=>'class#member(args)'};
rlm@0 230
rlm@0 231 sub topFrameGenerate
rlm@0 232 {
rlm@0 233 Delete('render');
rlm@0 234 param('render', 'query');
rlm@0 235 my $queryFrameUrl = self_url;
rlm@0 236
rlm@0 237 Delete('render');
rlm@0 238 param('render', 'noResults');
rlm@0 239 my $noResultsFrameUrl = self_url;
rlm@0 240
rlm@0 241 return
rlm@0 242 header(),
rlm@0 243 html(head(title('Javadoc search')),
rlm@0 244 frameset({-rows => '150,*'},
rlm@0 245 frame({-name => 'query', -src => $queryFrameUrl}),
rlm@0 246 frame({-name => $resultFrame, -src => $noResultsFrameUrl})));
rlm@0 247 }
rlm@0 248
rlm@0 249 sub noResultsGenerate
rlm@0 250 {
rlm@0 251 return
rlm@0 252 header,
rlm@0 253 start_html('Javadoc search'),
rlm@0 254 h2('No results yet'),
rlm@0 255 end_html,
rlm@0 256 "\n";
rlm@0 257 }
rlm@0 258
rlm@0 259 sub searchFormGenerate
rlm@0 260 {
rlm@0 261 Delete('render');
rlm@0 262
rlm@0 263 return
rlm@0 264 h1('Javadoc search'),
rlm@0 265 $resultFrame ? start_form(-target => $resultFrame, -action=>script_name) : start_form(-action=>script_name),
rlm@0 266 "Search pattern ",
rlm@0 267 textfield(-name=>'pattern', -size=>15),
rlm@0 268 " in ",
rlm@0 269 scrolling_list(-name=>'type',
rlm@0 270 -values=>[sort(keys(%$searchTypes))],
rlm@0 271 -labels=>$searchTypes,
rlm@0 272 -defaults=>['c'],
rlm@0 273 -size=>1),
rlm@0 274 " and display ",
rlm@0 275 scrolling_list(-name=>'results',
rlm@0 276 -values=>['1', '10', '20', '50', '0'],
rlm@0 277 -labels=>{'1'=>'1', '10'=>'10', '20'=>'20', '50'=>'50', '0'=>'All'},
rlm@0 278 -defaults=>['10'],
rlm@0 279 -size=>1),
rlm@0 280 " results ",
rlm@0 281 submit(-name=>'go', -value=>'Go'), submit(-name=>'lucky', -value=>'Go!'),
rlm@0 282 $resultFrame ? hidden(-name => 'render', -default => 'results') : "",
rlm@0 283 end_form,
rlm@0 284 $resultFrame ? "" : hr;
rlm@0 285 }
rlm@0 286
rlm@0 287 sub doSearch
rlm@0 288 {
rlm@0 289 my ($pattern, $type, $results) = @_;
rlm@0 290
rlm@0 291 if (! -r $indexFile)
rlm@0 292 {
rlm@0 293 print strong("Error: index file is not readable");
rlm@0 294 return;
rlm@0 295 }
rlm@0 296
rlm@0 297 if ($indexFile =~ /\.gz$/)
rlm@0 298 {
rlm@0 299 open(INPUT, "$gzip -dc \"$indexFile\" |") || die "unable to un-gzip $indexFile: $!\n";
rlm@0 300 }
rlm@0 301 else
rlm@0 302 {
rlm@0 303 open(INPUT, $indexFile) || die "unable to read $indexFile: $!\n";
rlm@0 304 }
rlm@0 305
rlm@0 306 my $docRoot = $ENV{'DOCUMENT_ROOT'};
rlm@0 307 my @matches;
rlm@0 308
rlm@0 309 INPUTLINE:
rlm@0 310 while(<INPUT>)
rlm@0 311 {
rlm@0 312 chomp;
rlm@0 313 my ($key, @urls) = split (/\t/);
rlm@0 314
rlm@0 315 for ($key)
rlm@0 316 {
rlm@0 317 if (($type eq "c" and /\#/) ||
rlm@0 318 ($type eq "cm" and !(/\#/ and !/\)/)) ||
rlm@0 319 ($type eq "cma" and !(/\#/ and /\)/)))
rlm@0 320 {
rlm@0 321 next INPUTLINE;
rlm@0 322 }
rlm@0 323 }
rlm@0 324
rlm@0 325 if ($key =~ /$pattern/ and ($results == 0 or $#matches < $results) )
rlm@0 326 {
rlm@0 327 push @matches, [ ( $key, map { s/$docRoot//; $_ } @urls ) ];
rlm@0 328 }
rlm@0 329
rlm@0 330 last if $results > 0 and $#matches >= $results;
rlm@0 331
rlm@0 332 }
rlm@0 333 close(INPUT);
rlm@0 334
rlm@0 335 return \@matches;
rlm@0 336 }
rlm@0 337
rlm@0 338 sub displayLuckyMatch
rlm@0 339 {
rlm@0 340 my $matches = shift;
rlm@0 341
rlm@0 342 if ( $#$matches < 0 )
rlm@0 343 {
rlm@0 344 print
rlm@0 345 header,
rlm@0 346 start_html('No matches'),
rlm@0 347 p("No matches"),
rlm@0 348 end_html;
rlm@0 349 }
rlm@0 350 else
rlm@0 351 {
rlm@0 352 print
rlm@0 353 $linkFrame ? header(-target => $linkFrame) : "",
rlm@0 354 redirect('-location'=> $$matches[0][1]);
rlm@0 355 }
rlm@0 356 }
rlm@0 357
rlm@0 358
rlm@0 359 sub displayMatches
rlm@0 360 {
rlm@0 361 my $matches = shift;
rlm@0 362
rlm@0 363 if ( $#$matches < 0 )
rlm@0 364 {
rlm@0 365 print p("No matches");
rlm@0 366 }
rlm@0 367 else
rlm@0 368 {
rlm@0 369 print
rlm@0 370 p(
rlm@0 371 "Searching pattern ", em(escapeHTML(param('pattern'))),
rlm@0 372 " in ", em(escapeHTML($$searchTypes{param('type')}))),
rlm@0 373 h2("Search results"),
rlm@0 374 "<ul>";
rlm@0 375
rlm@0 376 foreach my $match (@$matches)
rlm@0 377 {
rlm@0 378 my $searchKey = escapeHTML(shift @$match);
rlm@0 379 my $cnt = -1;
rlm@0 380 print li( map {
rlm@0 381 a( $linkFrame ? {-href => $_, -target => $linkFrame } : { -href => $_}, ( $cnt++ >= 0 ? "alt".($cnt) : $searchKey) )
rlm@0 382 } @$match );
rlm@0 383
rlm@0 384 }
rlm@0 385
rlm@0 386 print "</ul>";
rlm@0 387 }
rlm@0 388 }
rlm@0 389
rlm@0 390 #
rlm@0 391 # main
rlm@0 392 #
rlm@0 393 use vars qw / $opt_h $opt_r /;
rlm@0 394
rlm@0 395 if (server_software() eq 'cmdline')
rlm@0 396 {
rlm@0 397 getopts("rh");
rlm@0 398
rlm@0 399 if ($opt_h)
rlm@0 400 {
rlm@0 401 usage;
rlm@0 402 exit;
rlm@0 403 }
rlm@0 404
rlm@0 405 if ($opt_r)
rlm@0 406 {
rlm@0 407 indexRebuild;
rlm@0 408 indexWrite;
rlm@0 409 exit;
rlm@0 410 }
rlm@0 411 }
rlm@0 412
rlm@0 413
rlm@0 414 if (param('render'))
rlm@0 415 {
rlm@0 416 $resultFrame = 'results';
rlm@0 417 $linkFrame = '';
rlm@0 418 }
rlm@0 419
rlm@0 420 my $thisFrame = param('render');
rlm@0 421
rlm@0 422 if ($thisFrame eq 'topFrame')
rlm@0 423 {
rlm@0 424 print topFrameGenerate();
rlm@0 425 exit 0;
rlm@0 426 }
rlm@0 427 elsif ($thisFrame eq 'noResults')
rlm@0 428 {
rlm@0 429 print noResultsGenerate();
rlm@0 430 exit 0;
rlm@0 431 }
rlm@0 432
rlm@0 433 unless (param('lucky') and param('pattern'))
rlm@0 434 {
rlm@0 435 print
rlm@0 436 header,
rlm@0 437 start_html('Javadoc search'),
rlm@0 438 defined(param('pattern')) && $resultFrame ? "" : searchFormGenerate();
rlm@0 439 }
rlm@0 440
rlm@0 441 if (param('pattern'))
rlm@0 442 {
rlm@0 443 my $matches = doSearch(param('pattern'), param('type'), param('results'));
rlm@0 444
rlm@0 445 if (param('lucky'))
rlm@0 446 {
rlm@0 447 displayLuckyMatch($matches);
rlm@0 448 }
rlm@0 449 else
rlm@0 450 {
rlm@0 451 displayMatches($matches);
rlm@0 452 }
rlm@0 453 }
rlm@0 454 else
rlm@0 455 {
rlm@0 456 if ($thisFrame ne 'query')
rlm@0 457 {
rlm@0 458 print p('Specify non-blank search pattern');
rlm@0 459 }
rlm@0 460 }
rlm@0 461
rlm@0 462 unless (param('lucky') and param('pattern'))
rlm@0 463 {
rlm@0 464 print end_html;
rlm@0 465 }