KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jmeter > protocol > http > util > accesslog > LogFilter


1 // $Header: /home/cvs/jakarta-jmeter/src/protocol/http/org/apache/jmeter/protocol/http/util/accesslog/LogFilter.java,v 1.10 2004/03/13 19:49:14 sebb Exp $
2
/*
3  * Copyright 2003-2004 The Apache Software Foundation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17 */

18
19 package org.apache.jmeter.protocol.http.util.accesslog;
20
21 import java.util.ArrayList JavaDoc;
22
23 import org.apache.jmeter.junit.JMeterTestCase;
24 import org.apache.oro.text.regex.Pattern;
25 import org.apache.oro.text.regex.Perl5Compiler;
26 import org.apache.oro.text.regex.Perl5Matcher;
27
28 /**
29  * Description:<br>
30  * <br>
31  * LogFilter is a basic implementation of Filter
32  * interface. This implementation will keep a
33  * record of the filtered strings to avoid
34  * repeating the process unnecessarily.<p>
35  * The current implementation supports
36  * replacing the file extension. The reason for
37  * supporting this is from first hand experience
38  * porting an existing website to Tomcat + JSP.
39  * Later on we may want to provide the ability
40  * to replace the whole filename. If the need
41  * materializes, we can add it later.<p>
42  * Example of how to use it is provided in the
43  * main method. An example is provided below.
44  * <p>
45  * <pre>
46  * testf = new LogFilter();
47  * String[] incl = {"hello.html",
48  * "index.html",
49  * "/index.jsp"};
50  * String[] thefiles = {"/test/hello.jsp",
51  * "/test/one/hello.html",
52  * "hello.jsp",
53  * "hello.htm",
54  * "/test/open.jsp",
55  * "/test/open.html",
56  * "/index.jsp",
57  * "/index.jhtml",
58  * "newindex.jsp",
59  * "oldindex.jsp",
60  * "oldindex1.jsp",
61  * "oldindex2.jsp",
62  * "oldindex3.jsp",
63  * "oldindex4.jsp",
64  * "oldindex5.jsp",
65  * "oldindex6.jsp",
66  * "/test/index.htm"};
67  * testf.excludeFiles(incl);
68  * System.out.println(" ------------ exclude test -------------");
69  * for (int idx=0; idx &lt; thefiles.length; idx++){
70  * boolean fl = testf.isFiltered(thefiles[idx]);
71  * String line = testf.filter(thefiles[idx]);
72  * if (line != null){
73  * System.out.println("the file: "+ line);
74  * }
75  * }
76  * </pre>
77  * As a general note. Both isFiltered and filter()
78  * have to be called. Calling either one will not
79  * produce the desired result. isFiltered(string)
80  * will tell you if a string should be filtered.
81  * The second step is to filter the string, which
82  * will return null if it is filtered and replace
83  * any part of the string that should be replaced.
84  * <p>
85  *
86  * @version $Revision: 1.10 $ last updated $Date: 2004/03/13 19:49:14 $
87  * Created on: Jun 26, 2003<br>
88  */

89
90 public class LogFilter implements Filter
91 {
92
93     /** protected members used by class to filter **/
94     protected boolean CHANGEEXT = false;
95     protected String JavaDoc OLDEXT = null;
96     protected String JavaDoc NEWEXT = null;
97
98     protected String JavaDoc[] INCFILE = null;
99     protected String JavaDoc[] EXCFILE = null;
100     protected boolean FILEFILTER = false;
101     protected boolean USEFILE = true;
102
103     protected String JavaDoc[] INCPTRN = null;
104     protected String JavaDoc[] EXCPTRN = null;
105     protected boolean PTRNFILTER = false;
106
107     protected ArrayList JavaDoc EXCPATTERNS = new ArrayList JavaDoc();
108     protected ArrayList JavaDoc INCPATTERNS = new ArrayList JavaDoc();
109
110     protected String JavaDoc NEWFILE = null;
111
112     protected Perl5Matcher MATCHER = null;
113
114     /**
115      * The default constructor is empty
116      */

117     public LogFilter()
118     {
119         super();
120     }
121
122     /**
123      * The method will replace the file extension
124      * with the new one. You can either provide
125      * the extension without the period ".", or
126      * with. The method will check for period
127      * and add it if it isn't present.
128      * @see org.apache.jmeter.protocol.http.util.accesslog.Filter#setReplaceExtension(java.lang.String, java.lang.String)
129      */

130     public void setReplaceExtension(String JavaDoc oldext, String JavaDoc newext)
131     {
132         if (oldext != null && newext != null)
133         {
134             this.CHANGEEXT = true;
135             if (oldext.indexOf(".") < 0 && newext.indexOf(".") < 0)
136             {
137                 this.OLDEXT = "." + oldext;
138                 this.NEWEXT = "." + newext;
139             }
140             else
141             {
142                 this.OLDEXT = oldext;
143                 this.NEWEXT = newext;
144             }
145         }
146     }
147
148     /**
149      * Give the filter a list of files to include
150      * @param filenames
151      * @see org.apache.jmeter.protocol.http.util.accesslog.Filter#includeFiles(java.lang.String[])
152      */

153     public void includeFiles(String JavaDoc[] filenames)
154     {
155         if (filenames != null && filenames.length > 0)
156         {
157             INCFILE = filenames;
158             this.FILEFILTER = true;
159         }
160     }
161
162     /**
163      * Give the filter a list of files to exclude
164      * @param filenames
165      * @see org.apache.jmeter.protocol.http.util.accesslog.Filter#excludeFiles(java.lang.String[])
166      */

167     public void excludeFiles(String JavaDoc[] filenames)
168     {
169         if (filenames != null && filenames.length > 0)
170         {
171             EXCFILE = filenames;
172             this.FILEFILTER = true;
173         }
174     }
175
176     /**
177      * Give the filter a set of regular expressions
178      * to filter with for inclusion. This method hasn't
179      * been fully implemented and test yet. The
180      * implementation is not complete.
181      * @param regexp
182      * @see org.apache.jmeter.protocol.http.util.accesslog.Filter#includePattern(String[])
183      */

184     public void includePattern(String JavaDoc[] regexp)
185     {
186         if (regexp != null && regexp.length > 0)
187         {
188             INCPTRN = regexp;
189             this.PTRNFILTER = true;
190             // now we create the compiled pattern and
191
// add it to the arraylist
192
for (int idx = 0; idx < INCPTRN.length; idx++)
193             {
194                 this.INCPATTERNS.add(this.createPattern(INCPTRN[idx]));
195             }
196         }
197     }
198
199     /**
200      * Give the filter a set of regular expressions
201      * to filter with for exclusion. This method hasn't
202      * been fully implemented and test yet. The
203      * implementation is not complete.
204      * @param regexp
205      *
206      * @see org.apache.jmeter.protocol.http.util.accesslog.Filter#excludePattern(String[])
207      */

208     public void excludePattern(String JavaDoc[] regexp)
209     {
210         if (regexp != null && regexp.length > 0)
211         {
212             EXCPTRN = regexp;
213             this.PTRNFILTER = true;
214             // now we create the compiled pattern and
215
// add it to the arraylist
216
for (int idx = 0; idx < EXCPTRN.length; idx++)
217             {
218                 this.EXCPATTERNS.add(this.createPattern(EXCPTRN[idx]));
219             }
220         }
221     }
222
223     /**
224      * In the case of log filtering the important
225      * thing is whether the log entry should be
226      * used. Therefore, the method will only
227      * return true if the entry should be used.
228      * Since the interface defines both inclusion
229      * and exclusion, that means by default
230      * inclusion filtering assumes all entries
231      * are excluded unless it matches. In the
232      * case of exlusion filtering, it assumes
233      * all entries are included unless it
234      * matches, which means it should be
235      * excluded.
236      * @see org.apache.jmeter.protocol.http.util.accesslog.Filter#isFiltered(java.lang.String)
237      * @param path
238      * @return boolean
239      */

240     public boolean isFiltered(String JavaDoc path)
241     {
242         // we do a quick check to see if any
243
// filters are set. If not we just
244
// return false to be efficient.
245
if (this.FILEFILTER || this.PTRNFILTER || this.CHANGEEXT)
246         {
247             if (this.FILEFILTER)
248             {
249                 return filterFile(path);
250             }
251             else if (this.PTRNFILTER)
252             {
253                 return filterPattern(path);
254             }
255             else if (this.CHANGEEXT)
256             {
257                 return replaceExtension(path);
258             }
259             else
260             {
261                 return false;
262             }
263         }
264         else
265         {
266             return false;
267         }
268     }
269
270     /**
271      * Filter the file. The implementation performs
272      * the exclusion first before the inclusion.
273      * This means if a file name is in both string
274      * arrays, the exclusion will take priority.
275      * Depending on how users expect this to work,
276      * we may want to change the priority so that
277      * inclusion is performed first and exclusion
278      * second. Another possible alternative is to
279      * perform both inclusion and exclusion.
280      * Doing so would make the most sense if the
281      * method throws an exception and tells the
282      * user the same filename is in both the
283      * include and exclude array.
284      * @param file
285      * @return boolean
286      */

287     protected boolean filterFile(String JavaDoc file)
288     {
289         // double check this logic make sure it
290
// makes sense
291
if (this.EXCFILE != null)
292         {
293             return excFile(file);
294         }
295         else if (this.INCFILE != null)
296         {
297             return incFile(file);
298         }
299         return false;
300     }
301
302     /**
303      * Method implements the logic for filtering
304      * file name inclusion. The method iterates
305      * through the array and uses indexOf. Once
306      * it finds a match, it won't bother with
307      * the rest of the filenames in the array.
308      * @param text
309      * @return boolean include
310      */

311     public boolean incFile(String JavaDoc text)
312     {
313         // inclusion filter assumes most of
314
// the files are not wanted, therefore
315
// usefile is set to false unless it
316
// matches.
317
this.USEFILE = false;
318         for (int idx = 0; idx < this.INCFILE.length; idx++)
319         {
320             if (text.indexOf(this.INCFILE[idx]) > -1)
321             {
322                 this.USEFILE = true;
323                 break;
324             }
325         }
326         return this.USEFILE;
327     }
328
329     /**
330      * Method implements the logic for filtering
331      * file name exclusion. The method iterates
332      * through the array and uses indexOf. Once it
333      * finds a match, it won't bother with the
334      * rest of the filenames in the array.
335      * @param text
336      * @return boolean exclude
337      */

338     public boolean excFile(String JavaDoc text)
339     {
340         // exclusion filter assumes most of
341
// the files are used, therefore
342
// usefile is set to true, unless
343
// it matches.
344
this.USEFILE = true;
345         boolean exc = false;
346         for (int idx = 0; idx < this.EXCFILE.length; idx++)
347         {
348             if (text.indexOf(this.EXCFILE[idx]) > -1)
349             {
350                 exc = true;
351                 this.USEFILE = false;
352                 break;
353             }
354         }
355         return exc;
356     }
357
358     /**
359      * The current implemenation assumes
360      * the user has checked the regular
361      * expressions so that they don't cancel
362      * each other. The basic assumption is
363      * the method will return true if the
364      * text should be filtered. If not, it
365      * will return false, which means it
366      * should not be filtered.
367      * @param text
368      * @return boolean
369      */

370     protected boolean filterPattern(String JavaDoc text)
371     {
372         if (MATCHER == null)
373         {
374             MATCHER = new Perl5Matcher();
375         }
376         if (this.INCPTRN != null)
377         {
378             return incPattern(text);
379         }
380         else if (this.EXCPTRN != null)
381         {
382             return excPattern(text);
383         }
384         return false;
385     }
386
387     /**
388      * By default, the method assumes the entry is
389      * not included, unless it matches. In that case,
390      * it will return true.
391      * @param text
392      * @return true if text is included
393      */

394     protected boolean incPattern(String JavaDoc text)
395     {
396         this.USEFILE = false;
397         for (int idx = 0; idx < this.INCPATTERNS.size(); idx++)
398         {
399             if (MATCHER.contains(text, (Pattern) this.INCPATTERNS.get(idx)))
400             {
401                 this.USEFILE = true;
402                 break;
403             }
404         }
405         return this.USEFILE;
406     }
407
408     /**
409      * The method assumes by default the text is
410      * not excluded. If the text matches the
411      * pattern, it will then return true.
412      * @param text
413      * @return true if text is excluded
414      */

415     protected boolean excPattern(String JavaDoc text)
416     {
417         this.USEFILE = true;
418         boolean exc = false;
419         for (int idx = 0; idx < this.EXCPATTERNS.size(); idx++)
420         {
421             if (MATCHER.contains(text, (Pattern) this.EXCPATTERNS.get(idx)))
422             {
423                 exc = true;
424                 this.USEFILE = false;
425                 break;
426             }
427         }
428         return exc;
429     }
430
431     /**
432      * Method uses indexOf to replace the old
433      * extension with the new extesion. It
434      * might be good to use regular expression,
435      * but for now this is a simple method.
436      * The method isn't designed to replace
437      * multiple instances of the text, since
438      * that isn't how file extensions work.
439      * If the string contains more than one
440      * instance of the old extension, only
441      * the first instance will be replaced.
442      * @param text
443      * @return boolean
444      */

445     public boolean replaceExtension(String JavaDoc text)
446     {
447         int pt = text.indexOf(this.OLDEXT);
448         if (pt > -1)
449         {
450             int extsize = this.OLDEXT.length();
451             this.NEWFILE =
452                 text.substring(0, pt)
453                     + this.NEWEXT
454                     + text.substring(pt + extsize);
455             return true;
456         }
457         else
458         {
459             return false;
460         }
461     }
462
463     /**
464      * The current implementation checks the boolean
465      * if the text should be used or not. isFilter(
466      * string) has to be called first.
467      * @see org.apache.jmeter.protocol.http.util.accesslog.Filter#filter(java.lang.String)
468      */

469     public String JavaDoc filter(String JavaDoc text)
470     {
471         if (this.CHANGEEXT)
472         {
473             return this.NEWFILE;
474         }
475         else if (this.USEFILE)
476         {
477             return text;
478         }
479         else
480         {
481             return null;
482         }
483     }
484
485     /**
486      * create a new pattern object from
487      * the string.
488      * @param pattern
489      * @return Pattern
490      */

491     public Pattern createPattern(String JavaDoc pattern)
492     {
493         try
494         {
495             Perl5Compiler comp = new Perl5Compiler();
496             return comp.compile(pattern, Perl5Compiler.READ_ONLY_MASK);
497         }
498         catch (Exception JavaDoc exception)
499         {
500             exception.printStackTrace();
501             return null;
502         }
503     }
504
505 /////////////////////// Start of Test Code //////////////////////
506

507   public static class Test extends JMeterTestCase
508   {
509
510     private static final String JavaDoc TESTSTR = "/test/helloworld.html";
511     private static final String JavaDoc TESTSTROUT = "/test/helloworld.jsp";
512     
513     private static class TestData{
514         private final String JavaDoc file;
515         private final boolean exclfile;
516         private final boolean inclfile;
517         private final boolean exclpatt;
518         private final boolean inclpatt;
519         TestData(String JavaDoc f, boolean exf, boolean inf, boolean exp, boolean inp){
520             file = f;
521             exclfile = exf;
522             inclfile = inf;
523             exclpatt = exp;
524             inclpatt = inp;
525         }
526     }
527     
528     private static final String JavaDoc[] INCL = { "hello.html", "index.html", "/index.jsp" };
529     private static final String JavaDoc[] PATTERNS = { "index", ".jtml" };
530     private static final TestData[] TESTDATA = {
531                      // file exclf inclf exclp inclp
532
new TestData("/test/hello.jsp", true, false, true, false),
533         new TestData("/test/one/hello.html", false, true, true, false),
534         new TestData("hello.jsp", true, false, true, false),
535         new TestData("hello.htm", true, false, true, false),
536         new TestData("/test/open.jsp", true, false, true, false),
537         new TestData("/test/open.html", true, false, true, false),
538         new TestData("/index.jsp", false, true, false, true),
539         new TestData("/index.jhtml", true, false, false, true),
540         new TestData("newindex.jsp", true, false, false, true),
541         new TestData("oldindex.jsp", true, false, false, true),
542         new TestData("oldindex1.jsp", true, false, false, true),
543         new TestData("oldindex2.jsp", true, false, false, true),
544         new TestData("oldindex3.jsp", true, false, false, true),
545         new TestData("oldindex4.jsp", true, false, false, true),
546         new TestData("oldindex5.jsp", true, false, false, true),
547         new TestData("oldindex6.jsp", true, false, false, true),
548         new TestData("/test/index.htm", true, false, false, true)
549     };
550     
551
552     public void testConstruct()
553     {
554         new LogFilter();
555     }
556     
557     private LogFilter testf;
558
559     public void setUp()
560     {
561         testf = new LogFilter();
562     }
563     
564     public void testReplaceExtension()
565     {
566         testf.setReplaceExtension("html", "jsp");
567         testf.isFiltered(TESTSTR);// set the required variables
568
assertEquals(TESTSTROUT,testf.filter(TESTSTR));
569     }
570     
571     public void testExcludeFiles()
572     {
573         testf.excludeFiles(INCL);
574         for (int idx = 0; idx < TESTDATA.length; idx++)
575         {
576             TestData td = TESTDATA[idx];
577             String JavaDoc theFile = td.file;
578             boolean expect = td.exclfile;
579
580             testf.isFiltered(theFile);
581             String JavaDoc line = testf.filter(theFile);
582             if (line != null)
583             {
584                 assertTrue("Expect to accept "+theFile,expect);
585             }
586             else
587             {
588                 assertFalse("Expect to reject "+theFile,expect);
589             }
590         }
591     }
592
593     public void testIncludeFiles()
594     {
595         testf.includeFiles(INCL);
596         for (int idx = 0; idx < TESTDATA.length; idx++)
597         {
598             TestData td = TESTDATA[idx];
599             String JavaDoc theFile = td.file;
600             boolean expect = td.inclfile;
601
602             testf.isFiltered(theFile);
603             String JavaDoc line = testf.filter(theFile);
604             if (line != null)
605             {
606                 assertTrue("Expect to accept "+theFile,expect);
607             }
608             else
609             {
610                 assertFalse("Expect to reject "+theFile,expect);
611             }
612         }
613
614     }
615
616     public void testExcludePattern()
617     {
618         testf.excludePattern(PATTERNS);
619         for (int idx = 0; idx < TESTDATA.length; idx++)
620         {
621             TestData td = TESTDATA[idx];
622             String JavaDoc theFile = td.file;
623             boolean expect = td.exclpatt;
624
625             testf.isFiltered(theFile);
626             String JavaDoc line = testf.filter(theFile);
627             if (line != null)
628             {
629                 assertTrue("Expect to accept "+theFile,expect);
630             }
631             else
632             {
633                 assertFalse("Expect to reject "+theFile,expect);
634             }
635         }
636     }
637
638     public void testIncludePattern()
639     {
640         testf.includePattern(PATTERNS);
641         for (int idx = 0; idx < TESTDATA.length; idx++)
642         {
643             TestData td = TESTDATA[idx];
644             String JavaDoc theFile = td.file;
645             boolean expect = td.inclpatt;
646
647             testf.isFiltered(theFile);
648             String JavaDoc line = testf.filter(theFile);
649             if (line != null)
650             {
651                 assertTrue("Expect to accept "+theFile,expect);
652             }
653             else
654             {
655                 assertFalse("Expect to reject "+theFile,expect);
656             }
657         }
658     }
659   }
660 }
661
Popular Tags