KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > archive > crawler > util > LogReader


1 /* Copyright (C) 2003 Internet Archive.
2  *
3  * This file is part of the Heritrix web crawler (crawler.archive.org).
4  *
5  * Heritrix is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser Public License as published by
7  * the Free Software Foundation; either version 2.1 of the License, or
8  * any later version.
9  *
10  * Heritrix is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser Public License
16  * along with Heritrix; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */

19 package org.archive.crawler.util;
20
21 import java.io.BufferedReader JavaDoc;
22 import java.io.File JavaDoc;
23 import java.io.FileNotFoundException JavaDoc;
24 import java.io.FileReader JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.InputStreamReader JavaDoc;
27 import java.io.RandomAccessFile JavaDoc;
28 import java.text.DecimalFormat JavaDoc;
29 import java.text.NumberFormat JavaDoc;
30 import java.util.LinkedList JavaDoc;
31 import java.util.regex.Matcher JavaDoc;
32 import java.util.regex.Pattern JavaDoc;
33 import java.util.regex.PatternSyntaxException JavaDoc;
34
35 import org.archive.crawler.framework.CrawlController;
36 import org.archive.io.CompositeFileReader;
37 import org.archive.util.ArchiveUtils;
38
39 /**
40  * This class contains a variety of methods for reading log files (or other text
41  * files containing repeated lines with similar information).
42  * <p>
43  * All methods are static.
44  *
45  * @author Kristinn Sigurdsson
46  */

47
48 public class LogReader
49 {
50     /**
51      * Returns the entire file. Useful for smaller files.
52      *
53      * @param aFileName a file name
54      * @return The String representation of the entire file.
55      * Null is returned if errors occur (file not found or io exception)
56      */

57     public static String JavaDoc get(String JavaDoc aFileName){
58         try {
59             return get(new FileReader JavaDoc(aFileName));
60         } catch (FileNotFoundException JavaDoc e) {
61             e.printStackTrace();
62             return null;
63         }
64     }
65
66     /**
67      * Reads entire contents of reader, returns as string.
68      *
69      * @param reader
70      * @return String of entire contents; null for any error.
71      */

72     public static String JavaDoc get(InputStreamReader JavaDoc reader){
73         StringBuffer JavaDoc ret = new StringBuffer JavaDoc();
74         try{
75             BufferedReader JavaDoc bf = new BufferedReader JavaDoc(reader, 8192);
76
77             String JavaDoc line = null;
78             while ((line = bf.readLine()) != null) {
79                 ret.append(line);
80                 ret.append("\n");
81             }
82         } catch(IOException JavaDoc e){
83             e.printStackTrace();
84             return null;
85         }
86         return ret.toString();
87     }
88
89     /**
90      * Gets a portion of a log file. Starting at a given line number and the n-1
91      * lines following that one or until the end of the log if that is reached
92      * first.
93      *
94      * @param aFileName The filename of the log/file
95      * @param lineNumber The number of the first line to get (if larger then the
96      * file an empty string will be returned)
97      * @param n How many lines to return (total, including the one indicated by
98      * lineNumber). If smaller then 1 then an empty string
99      * will be returned.
100      *
101      * @return An array of two strings is returned. At index 0 a portion of the
102      * file starting at lineNumber and reaching lineNumber+n is located.
103      * At index 1 there is an informational string about how large a
104      * segment of the file is being returned.
105      * Null is returned if errors occur (file not found or io exception)
106      */

107     public static String JavaDoc[] get(String JavaDoc aFileName, int lineNumber, int n)
108     {
109         File JavaDoc f = new File JavaDoc(aFileName);
110         long logsize = f.length();
111         try {
112             return get(new FileReader JavaDoc(aFileName),lineNumber,n,logsize);
113         } catch (FileNotFoundException JavaDoc e) {
114             e.printStackTrace();
115             return null;
116         }
117     }
118
119     /**
120      * Gets a portion of a log spread across a numbered series of files.
121      *
122      * Starting at a given line number and the n-1 lines following that
123      * one or until the end of the log if that is reached
124      * first.
125      *
126      * @param aFileName The filename of the log/file
127      * @param lineNumber The number of the first line to get (if larger then the
128      * file an empty string will be returned)
129      * @param n How many lines to return (total, including the one indicated by
130      * lineNumber). If smaller then 1 then an empty string
131      * will be returned.
132      *
133      * @return An array of two strings is returned. At index 0 a portion of the
134      * file starting at lineNumber and reaching lineNumber+n is located.
135      * At index 1 there is an informational string about how large a
136      * segment of the file is being returned.
137      * Null is returned if errors occur (file not found or io exception)
138      */

139     public static String JavaDoc[] getFromSeries(String JavaDoc aFileName, int lineNumber, int n)
140     {
141         File JavaDoc f = new File JavaDoc(aFileName);
142         long logsize = f.length();
143         try {
144             return get(seriesReader(aFileName),lineNumber,n,logsize);
145         } catch (IOException JavaDoc e) {
146             e.printStackTrace();
147             return null;
148         }
149     }
150
151     public static String JavaDoc buildDisplayingHeader(int len, long logsize)
152     {
153         double percent = 0.0;
154         if (logsize != 0) {
155             percent = ((double) len/logsize) * 100;
156         }
157         return "Displaying: " + ArchiveUtils.doubleToString(percent,1) +
158             "% of " + ArchiveUtils.formatBytesForDisplay(logsize);
159     }
160
161     /**
162      * Gets a portion of a log file. Starting at a given line number and the n-1
163      * lines following that one or until the end of the log if that is reached
164      * first.
165      *
166      * @param reader source to scan for lines
167      * @param lineNumber The number of the first line to get (if larger then the
168      * file an empty string will be returned)
169      * @param n How many lines to return (total, including the one indicated by
170      * lineNumber). If smaller then 1 then an empty string
171      * will be returned.
172      *
173      * @param logsize total size of source
174      * @return An array of two strings is returned. At index 0 a portion of the
175      * file starting at lineNumber and reaching lineNumber+n is located.
176      * At index 1 there is an informational string about how large a
177      * segment of the file is being returned.
178      * Null is returned if errors occur (file not found or io exception)
179      */

180     public static String JavaDoc[] get(InputStreamReader JavaDoc reader,
181                                int lineNumber,
182                                int n,
183                                long logsize)
184     {
185         StringBuffer JavaDoc ret = new StringBuffer JavaDoc();
186         String JavaDoc info = null;
187         try{
188             BufferedReader JavaDoc bf = new BufferedReader JavaDoc(reader, 8192);
189
190             String JavaDoc line = null;
191             int i=1;
192             while ((line = bf.readLine()) != null) {
193                 if(i >= lineNumber && i < (lineNumber+n))
194                 {
195                     ret.append(line);
196                     ret.append('\n');
197                 } else if( i >= (lineNumber+n)){
198                     break;
199                 }
200                 i++;
201             }
202             info = buildDisplayingHeader(ret.length(), logsize);
203         }catch(IOException JavaDoc e){
204             e.printStackTrace();
205             return null;
206         }
207         String JavaDoc[] tmp = {ret.toString(),info};
208         return tmp;
209     }
210
211     /**
212      * Return the line number of the first line in the
213      * log/file that matches a given regular expression.
214      *
215      * @param aFileName The filename of the log/file
216      * @param regExpr The regular expression that is to be used
217      * @return The line number (counting from 1, not zero) of the first line
218      * that matches the given regular expression. -1 is returned if no
219      * line matches the regular expression. -1 also is returned if
220      * errors occur (file not found, io exception etc.)
221      */

222     public static int findFirstLineContaining(String JavaDoc aFileName, String JavaDoc regExpr)
223     {
224         try {
225             return findFirstLineContaining(new FileReader JavaDoc(aFileName), regExpr);
226         } catch (FileNotFoundException JavaDoc e) {
227             e.printStackTrace();
228             return -1;
229         }
230     }
231
232     /**
233      * Return the line number of the first line in the
234      * log/file that begins with the given string.
235      *
236      * @param aFileName The filename of the log/file
237      * @param prefix The prefix string to match
238      * @return The line number (counting from 1, not zero) of the first line
239      * that matches the given regular expression. -1 is returned if no
240      * line matches the regular expression. -1 also is returned if
241      * errors occur (file not found, io exception etc.)
242      */

243     public static int findFirstLineBeginningFromSeries(String JavaDoc aFileName,
244                                                         String JavaDoc prefix)
245     {
246         try {
247             return findFirstLineBeginning(seriesReader(aFileName), prefix);
248         } catch (IOException JavaDoc e) {
249             e.printStackTrace();
250             return -1;
251         }
252     }
253     
254     /**
255      * Return the line number of the first line in the
256      * log/file that that begins with the given string.
257      *
258      * @param reader The reader of the log/file
259      * @param prefix The prefix string to match
260      * @return The line number (counting from 1, not zero) of the first line
261      * that matches the given regular expression. -1 is returned if no
262      * line matches the regular expression. -1 also is returned if
263      * errors occur (file not found, io exception etc.)
264      */

265     public static int findFirstLineBeginning(InputStreamReader JavaDoc reader,
266                                               String JavaDoc prefix)
267     {
268
269         try{
270             BufferedReader JavaDoc bf = new BufferedReader JavaDoc(reader, 8192);
271
272             String JavaDoc line = null;
273             int i = 1;
274             while ((line = bf.readLine()) != null) {
275                 if(line.startsWith(prefix)){
276                     // Found a match
277
return i;
278                 }
279                 i++;
280             }
281         } catch(IOException JavaDoc e){
282             e.printStackTrace();
283         }
284         return -1;
285     }
286     
287     /**
288      * Return the line number of the first line in the
289      * log/file that matches a given regular expression.
290      *
291      * @param aFileName The filename of the log/file
292      * @param regExpr The regular expression that is to be used
293      * @return The line number (counting from 1, not zero) of the first line
294      * that matches the given regular expression. -1 is returned if no
295      * line matches the regular expression. -1 also is returned if
296      * errors occur (file not found, io exception etc.)
297      */

298     public static int findFirstLineContainingFromSeries(String JavaDoc aFileName,
299                                                         String JavaDoc regExpr)
300     {
301         try {
302             return findFirstLineContaining(seriesReader(aFileName), regExpr);
303         } catch (IOException JavaDoc e) {
304             e.printStackTrace();
305             return -1;
306         }
307     }
308
309     /**
310      * Return the line number of the first line in the
311      * log/file that matches a given regular expression.
312      *
313      * @param reader The reader of the log/file
314      * @param regExpr The regular expression that is to be used
315      * @return The line number (counting from 1, not zero) of the first line
316      * that matches the given regular expression. -1 is returned if no
317      * line matches the regular expression. -1 also is returned if
318      * errors occur (file not found, io exception etc.)
319      */

320     public static int findFirstLineContaining(InputStreamReader JavaDoc reader,
321                                               String JavaDoc regExpr)
322     {
323         Pattern JavaDoc p = Pattern.compile(regExpr);
324
325         try{
326             BufferedReader JavaDoc bf = new BufferedReader JavaDoc(reader, 8192);
327
328             String JavaDoc line = null;
329             int i = 1;
330             while ((line = bf.readLine()) != null) {
331                 if(p.matcher(line).matches()){
332                     // Found a match
333
return i;
334                 }
335                 i++;
336             }
337         } catch(IOException JavaDoc e){
338             e.printStackTrace();
339         }
340         return -1;
341     }
342
343     /**
344      * Returns all lines in a log/file matching a given regular expression.
345      * Possible to get lines immediately following the matched line. Also
346      * possible to have each line prepended by it's line number.
347      *
348      * @param aFileName The filename of the log/file
349      * @param regExpr The regular expression that is to be used
350      * @param addLines How many lines (in addition to the matched line) to add.
351      * A value less then 1 will mean that only the matched line
352      * will be included. If another matched line is hit before
353      * we reach this limit it will be included and this counter
354      * effectively reset for it.
355      * @param prependLineNumbers If true, then each line will be prepended by
356      * it's line number in the file.
357      * @param skipFirstMatches The first number of matches up to this value will
358      * be skipped over.
359      * @param numberOfMatches Once past matches that are to be skipped this many
360      * matches will be added to the return value. A
361      * value of 0 will cause all matching lines to be
362      * included.
363      * @return An array of two strings is returned. At index 0 tall lines in a
364      * log/file matching a given regular expression is located.
365      * At index 1 there is an informational string about how large a
366      * segment of the file is being returned.
367      * Null is returned if errors occur (file not found or io exception)
368      * If a PatternSyntaxException occurs, it's error message will be
369      * returned and the informational string will be empty (not null).
370      */

371     public static String JavaDoc[] getByRegExpr(String JavaDoc aFileName,
372                                         String JavaDoc regExpr,
373                                         int addLines,
374                                         boolean prependLineNumbers,
375                                         int skipFirstMatches,
376                                         int numberOfMatches) {
377         try {
378             File JavaDoc f = new File JavaDoc(aFileName);
379             return getByRegExpr(
380                     new FileReader JavaDoc(f),
381                     regExpr,
382                     addLines,
383                     prependLineNumbers,
384                     skipFirstMatches,
385                     numberOfMatches,
386                     f.length());
387         } catch (FileNotFoundException JavaDoc e) {
388             e.printStackTrace();
389             return null;
390         }
391     }
392
393     /**
394      * Returns all lines in a log/file matching a given regular expression.
395      * Possible to get lines immediately following the matched line. Also
396      * possible to have each line prepended by it's line number.
397      *
398      * @param aFileName The filename of the log/file
399      * @param regExpr The regular expression that is to be used
400      * @param addLines How many lines (in addition to the matched line) to add.
401      * A value less then 1 will mean that only the matched line
402      * will be included. If another matched line is hit before
403      * we reach this limit it will be included and this counter
404      * effectively reset for it.
405      * @param prependLineNumbers If true, then each line will be prepended by
406      * it's line number in the file.
407      * @param skipFirstMatches The first number of matches up to this value will
408      * be skipped over.
409      * @param numberOfMatches Once past matches that are to be skipped this many
410      * matches will be added to the return value. A
411      * value of 0 will cause all matching lines to be
412      * included.
413      * @return An array of two strings is returned. At index 0 tall lines in a
414      * log/file matching a given regular expression is located.
415      * At index 1 there is an informational string about how large a
416      * segment of the file is being returned.
417      * Null is returned if errors occur (file not found or io exception)
418      * If a PatternSyntaxException occurs, it's error message will be
419      * returned and the informational string will be empty (not null).
420      */

421     public static String JavaDoc[] getByRegExprFromSeries(String JavaDoc aFileName,
422                                       String JavaDoc regExpr,
423                                       int addLines,
424                                       boolean prependLineNumbers,
425                                       int skipFirstMatches,
426                                       int numberOfMatches) {
427         try {
428             File JavaDoc f = new File JavaDoc(aFileName);
429             return getByRegExpr(
430                     seriesReader(aFileName),
431                     regExpr,
432                     addLines,
433                     prependLineNumbers,
434                     skipFirstMatches,
435                     numberOfMatches,
436                     f.length());
437         } catch (IOException JavaDoc e) {
438             e.printStackTrace();
439             return null;
440         }
441     }
442
443     /**
444      * Returns all lines in a log/file matching a given regular expression.
445      * Possible to get lines immediately following the matched line. Also
446      * possible to have each line prepended by it's line number.
447      *
448      * @param reader The reader of the log/file
449      * @param regExpr The regular expression that is to be used
450      * @param addLines How many lines (in addition to the matched line) to add.
451      * A value less then 1 will mean that only the matched line
452      * will be included. If another matched line is hit before
453      * we reach this limit it will be included and this counter
454      * effectively reset for it.
455      * @param prependLineNumbers If true, then each line will be prepended by
456      * it's line number in the file.
457      * @param skipFirstMatches The first number of matches up to this value will
458      * be skipped over.
459      * @param numberOfMatches Once past matches that are to be skipped this many
460      * matches will be added to the return value. A
461      * value of 0 will cause all matching lines to be
462      * included.
463      * @param logsize Size of the log in bytes
464      * @return An array of two strings is returned. At index 0 all lines in a
465      * log/file matching a given regular expression is located.
466      * At index 1 there is an informational string about how large a
467      * segment of the file is being returned.
468      * Null is returned if errors occur (file not found or io exception)
469      * If a PatternSyntaxException occurs, it's error message will be
470      * returned and the informational string will be empty (not null).
471      */

472     public static String JavaDoc[] getByRegExpr(InputStreamReader JavaDoc reader,
473                                       String JavaDoc regExpr,
474                                       int addLines,
475                                       boolean prependLineNumbers,
476                                       int skipFirstMatches,
477                                       int numberOfMatches,
478                                       long logsize) {
479         StringBuffer JavaDoc ret = new StringBuffer JavaDoc();
480         String JavaDoc info = "";
481
482         try{
483             Pattern JavaDoc p = Pattern.compile(regExpr);
484             BufferedReader JavaDoc bf = new BufferedReader JavaDoc(reader, 8192);
485
486             String JavaDoc line = null;
487             int i = 1;
488             boolean doAdd = false;
489             int addCount = 0;
490             long linesMatched = 0;
491             while ((line = bf.readLine()) != null) {
492                 if(p.matcher(line).matches()){
493                     // Found a match
494
if(numberOfMatches > 0 &&
495                             linesMatched >= skipFirstMatches + numberOfMatches){
496                         // Ok, we are done.
497
break;
498                     }
499                     linesMatched++;
500                     if(linesMatched > skipFirstMatches){
501                         if(prependLineNumbers){
502                             ret.append(i);
503                             ret.append(". ");
504                         }
505                         ret.append(line);
506                         ret.append("\n");
507                         doAdd = true;
508                         addCount = 0;
509                     }
510                 } else if(doAdd) {
511                     if(addCount < addLines){
512                         //Ok, still within addLines
513
linesMatched++;
514                         if(prependLineNumbers){
515                             ret.append(i);
516                             ret.append(". ");
517                         }
518                         ret.append(line);
519                         ret.append("\n");
520                     }else{
521                         doAdd = false;
522                         addCount = 0;
523                     }
524                 }
525                 i++;
526             }
527             info = buildDisplayingHeader(ret.length(), logsize);
528         }catch(FileNotFoundException JavaDoc e){
529             return null;
530         }catch(IOException JavaDoc e){
531             e.printStackTrace();
532             return null;
533         }catch(PatternSyntaxException JavaDoc e){
534             ret = new StringBuffer JavaDoc(e.getMessage());
535         }
536         String JavaDoc[] tmp = {ret.toString(),info};
537         return tmp;
538     }
539
540     /**
541      * Returns all lines in a log/file matching a given regular expression.
542      * Possible to get lines immediately following the matched line. Also
543      * possible to have each line prepended by it's line number.
544      *
545      * @param aFileName The filename of the log/file
546      * @param regExpr The regular expression that is to be used
547      * @param addLines Any lines following a match that <b>begin</b> with this
548      * string will also be included. We will stop including new
549      * lines once we hit the first that does not match.
550      * @param prependLineNumbers If true, then each line will be prepended by
551      * it's line number in the file.
552      * @param skipFirstMatches The first number of matches up to this value will
553      * be skipped over.
554      * @param numberOfMatches Once past matches that are to be skipped this many
555      * matches will be added to the return value. A
556      * value of 0 will cause all matching lines to be
557      * included.
558      * @return An array of two strings is returned. At index 0 tall lines in a
559      * log/file matching a given regular expression is located.
560      * At index 1 there is an informational string about how large a
561      * segment of the file is being returned.
562      * Null is returned if errors occur (file not found or io exception)
563      * If a PatternSyntaxException occurs, it's error message will be
564      * returned and the informational string will be empty (not null).
565      */

566     public static String JavaDoc[] getByRegExpr(String JavaDoc aFileName,
567                                         String JavaDoc regExpr,
568                                         String JavaDoc addLines,
569                                         boolean prependLineNumbers,
570                                         int skipFirstMatches,
571                                         int numberOfMatches){
572         try {
573             File JavaDoc f = new File JavaDoc(aFileName);
574             return getByRegExpr(
575                     new FileReader JavaDoc(f),
576                     regExpr,
577                     addLines,
578                     prependLineNumbers,
579                     skipFirstMatches,
580                     numberOfMatches,
581                     f.length());
582         } catch (FileNotFoundException JavaDoc e) {
583             e.printStackTrace();
584             return null;
585         }
586     }
587
588     /**
589      * Returns all lines in a log/file matching a given regular expression.
590      * Possible to get lines immediately following the matched line. Also
591      * possible to have each line prepended by it's line number.
592      *
593      * @param aFileName The filename of the log/file
594      * @param regExpr The regular expression that is to be used
595      * @param addLines Any lines following a match that <b>begin</b> with this
596      * string will also be included. We will stop including new
597      * lines once we hit the first that does not match.
598      * @param prependLineNumbers If true, then each line will be prepended by
599      * it's line number in the file.
600      * @param skipFirstMatches The first number of matches up to this value will
601      * be skipped over.
602      * @param numberOfMatches Once past matches that are to be skipped this many
603      * matches will be added to the return value. A
604      * value of 0 will cause all matching lines to be
605      * included.
606      * @return An array of two strings is returned. At index 0 tall lines in a
607      * log/file matching a given regular expression is located.
608      * At index 1 there is an informational string about how large a
609      * segment of the file is being returned.
610      * Null is returned if errors occur (file not found or io exception)
611      * If a PatternSyntaxException occurs, it's error message will be
612      * returned and the informational string will be empty (not null).
613      */

614     public static String JavaDoc[] getByRegExprFromSeries(String JavaDoc aFileName,
615                                                   String JavaDoc regExpr,
616                                                   String JavaDoc addLines,
617                                                   boolean prependLineNumbers,
618                                                   int skipFirstMatches,
619                                                   int numberOfMatches){
620         try {
621             File JavaDoc f = new File JavaDoc(aFileName);
622             return getByRegExpr(
623                     seriesReader(aFileName),
624                     regExpr,
625                     addLines,
626                     prependLineNumbers,
627                     skipFirstMatches,
628                     numberOfMatches,
629                     f.length());
630         } catch (IOException JavaDoc e) {
631             e.printStackTrace();
632             return null;
633         }
634     }
635
636     /**
637      * Returns all lines in a log/file matching a given regular expression.
638      * Possible to get lines immediately following the matched line. Also
639      * possible to have each line prepended by it's line number.
640      *
641      * @param reader The reader of the log/file
642      * @param regExpr The regular expression that is to be used
643      * @param addLines Any lines following a match that <b>begin</b> with this
644      * string will also be included. We will stop including new
645      * lines once we hit the first that does not match.
646      * @param prependLineNumbers If true, then each line will be prepended by
647      * it's line number in the file.
648      * @param skipFirstMatches The first number of matches up to this value will
649      * be skipped over.
650      * @param numberOfMatches Once past matches that are to be skipped this many
651      * matches will be added to the return value. A
652      * value of 0 will cause all matching lines to be
653      * included.
654      * @param logsize Size of the log in bytes
655      * @return An array of two strings is returned. At index 0 tall lines in a
656      * log/file matching a given regular expression is located.
657      * At index 1 there is an informational string about how large a
658      * segment of the file is being returned.
659      * Null is returned if errors occur (file not found or io exception)
660      * If a PatternSyntaxException occurs, it's error message will be
661      * returned and the informational string will be empty (not null).
662      */

663     public static String JavaDoc[] getByRegExpr(InputStreamReader JavaDoc reader,
664                                         String JavaDoc regExpr,
665                                         String JavaDoc addLines,
666                                         boolean prependLineNumbers,
667                                         int skipFirstMatches,
668                                         int numberOfMatches,
669                                         long logsize) {
670         StringBuffer JavaDoc ret = new StringBuffer JavaDoc();
671         String JavaDoc info = "";
672         try{
673             Matcher JavaDoc m = Pattern.compile(regExpr).matcher("");
674             BufferedReader JavaDoc bf = new BufferedReader JavaDoc(reader, 8192);
675
676             String JavaDoc line = null;
677             int i = 1;
678             boolean doAdd = false;
679             long linesMatched = 0;
680             while ((line = bf.readLine()) != null) {
681                 m.reset(line);
682                 if(m.matches()){
683                     // Found a match
684
if(numberOfMatches > 0 &&
685                             linesMatched >= skipFirstMatches + numberOfMatches){
686                         // Ok, we are done.
687
break;
688                     }
689                     linesMatched++;
690                     if(linesMatched > skipFirstMatches){
691                         if(prependLineNumbers){
692                             ret.append(i);
693                             ret.append(". ");
694                         }
695                         ret.append(line);
696                         ret.append("\n");
697                         doAdd = true;
698                     }
699                 } else if(doAdd) {
700                     if(line.indexOf(addLines)==0){
701                         linesMatched++;
702                         //Ok, line begins with 'addLines'
703
if(prependLineNumbers){
704                             ret.append(i);
705                             ret.append(". ");
706                         }
707                         ret.append(line);
708                         ret.append("\n");
709                     }else{
710                         doAdd = false;
711                     }
712                 }
713                 i++;
714             }
715             info = buildDisplayingHeader(ret.length(), logsize);
716         }catch(FileNotFoundException JavaDoc e){
717             return null;
718         }catch(IOException JavaDoc e){
719             e.printStackTrace();
720             return null;
721         }catch(PatternSyntaxException JavaDoc e){
722             ret = new StringBuffer JavaDoc(e.getMessage());
723         }
724         String JavaDoc[] tmp = {ret.toString(),info};
725         return tmp;
726     }
727
728     /**
729      * Implementation of a unix-like 'tail' command
730      *
731      * @param aFileName a file name String
732      * @return An array of two strings is returned. At index 0 the String
733      * representation of at most 10 last lines is located.
734      * At index 1 there is an informational string about how large a
735      * segment of the file is being returned.
736      * Null is returned if errors occur (file not found or io exception)
737      */

738     public static String JavaDoc[] tail(String JavaDoc aFileName) {
739         return tail(aFileName, 10);
740     }
741
742     /**
743      * Implementation of a unix-like 'tail -n' command
744      *
745      * @param aFileName a file name String
746      * @param n int number of lines to be returned
747      * @return An array of two strings is returned. At index 0 the String
748      * representation of at most n last lines is located.
749      * At index 1 there is an informational string about how large a
750      * segment of the file is being returned.
751      * Null is returned if errors occur (file not found or io exception)
752      */

753     public static String JavaDoc[] tail(String JavaDoc aFileName, int n) {
754         try {
755             return tail(new RandomAccessFile JavaDoc(new File JavaDoc(aFileName),"r"),n);
756         } catch (FileNotFoundException JavaDoc e) {
757             e.printStackTrace();
758             return null;
759         }
760     }
761
762     /**
763      * Implementation of a unix-like 'tail -n' command
764      *
765      * @param raf a RandomAccessFile to tail
766      * @param n int number of lines to be returned
767      * @return An array of two strings is returned. At index 0 the String
768      * representation of at most n last lines is located.
769      * At index 1 there is an informational string about how large a
770      * segment of the file is being returned.
771      * Null is returned if errors occur (file not found or io exception)
772      */

773     public static String JavaDoc[] tail(RandomAccessFile JavaDoc raf, int n) {
774         int BUFFERSIZE = 1024;
775         long pos;
776         long endPos;
777         long lastPos;
778         int numOfLines = 0;
779         String JavaDoc info=null;
780         byte[] buffer = new byte[BUFFERSIZE];
781         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
782         try {
783             endPos = raf.length();
784             lastPos = endPos;
785
786             // Check for non-empty file
787
// Check for newline at EOF
788
if (endPos > 0) {
789                 byte[] oneByte = new byte[1];
790                 raf.seek(endPos - 1);
791                 raf.read(oneByte);
792                 if ((char) oneByte[0] != '\n') {
793                     numOfLines++;
794                 }
795             }
796
797             do {
798                 // seek back BUFFERSIZE bytes
799
// if length of the file if less then BUFFERSIZE start from BOF
800
pos = 0;
801                 if ((lastPos - BUFFERSIZE) > 0) {
802                     pos = lastPos - BUFFERSIZE;
803                 }
804                 raf.seek(pos);
805                 // If less then BUFFERSIZE avaliable read the remaining bytes
806
if ((lastPos - pos) < BUFFERSIZE) {
807                     int remainer = (int) (lastPos - pos);
808                     buffer = new byte[remainer];
809                 }
810                 raf.readFully(buffer);
811                 // in the buffer seek back for newlines
812
for (int i = buffer.length - 1; i >= 0; i--) {
813                     if ((char) buffer[i] == '\n') {
814                         numOfLines++;
815                         // break if we have last n lines
816
if (numOfLines > n) {
817                             pos += (i + 1);
818                             break;
819                         }
820                     }
821                 }
822                 // reset last postion
823
lastPos = pos;
824             } while ((numOfLines <= n) && (pos != 0));
825
826             // print last n line starting from last postion
827
for (pos = lastPos; pos < endPos; pos += buffer.length) {
828                 raf.seek(pos);
829                 if ((endPos - pos) < BUFFERSIZE) {
830                     int remainer = (int) (endPos - pos);
831                     buffer = new byte[remainer];
832                 }
833                 raf.readFully(buffer);
834                 sb.append(new String JavaDoc(buffer));
835             }
836
837             info = buildDisplayingHeader(sb.length(), raf.length());
838         } catch (FileNotFoundException JavaDoc e) {
839             sb = null;
840         } catch (IOException JavaDoc e) {
841             e.printStackTrace();
842             sb = null;
843         } finally {
844             try {
845                 if (raf != null) {
846                     raf.close();
847                 }
848             } catch (IOException JavaDoc e) {
849                 e.printStackTrace();
850             }
851         }
852         if(sb==null){
853             return null;
854         }
855         String JavaDoc[] tmp = {sb.toString(),info};
856         return tmp;
857     }
858
859     /**
860      * @param fileName
861      * @return
862      * @throws IOException
863      */

864     private static CompositeFileReader seriesReader(String JavaDoc fileName)
865     throws IOException JavaDoc {
866         LinkedList JavaDoc<File JavaDoc> filenames = new LinkedList JavaDoc<File JavaDoc>();
867         int seriesNumber = 1;
868         NumberFormat JavaDoc fmt = new DecimalFormat JavaDoc("00000");
869         String JavaDoc predecessorFilename =
870             fileName.substring(0,fileName.length()
871             - CrawlController.CURRENT_LOG_SUFFIX.length())
872             + fmt.format(seriesNumber);
873         while((new File JavaDoc(predecessorFilename)).exists()) {
874             filenames.add(new File JavaDoc(predecessorFilename));
875             seriesNumber++;
876             predecessorFilename =
877                 fileName.substring(0,fileName.length()
878                 - CrawlController.CURRENT_LOG_SUFFIX.length())
879                 + fmt.format(seriesNumber);
880         }
881         filenames.add(new File JavaDoc(fileName)); // add current file
882
return new CompositeFileReader(filenames);
883     }
884 }
885
Popular Tags