You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-dev@logging.apache.org by ce...@apache.org on 2005/02/01 15:46:21 UTC

cvs commit: logging-log4j/tests/src/java/org/apache/log4j/lbel EventEvaluationTest.java TokenStreamTest.java

ceki        2005/02/01 06:46:21

  Modified:    src/java/org/apache/log4j/lbel/comparator Comparator.java
                        StringComparator.java
               src/java/org/apache/log4j/lbel Token.java Parser.java
                        TokenStream.java EventEvaluator.java
               tests/src/java/org/apache/log4j/lbel
                        EventEvaluationTest.java TokenStreamTest.java
  Log:
  - Fixed problem with StreamTokenizer which would incorrectly drop backslash '\' characters in quoted literals.
    This means that real world patterns can be processed.
  
    For example, one can now write "'message ~ 'hello\s*world'  "
  
  Revision  Changes    Path
  1.2       +8 -1      logging-log4j/src/java/org/apache/log4j/lbel/comparator/Comparator.java
  
  Index: Comparator.java
  ===================================================================
  RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/lbel/comparator/Comparator.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Comparator.java	27 Jan 2005 19:25:08 -0000	1.1
  +++ Comparator.java	1 Feb 2005 14:46:21 -0000	1.2
  @@ -28,5 +28,12 @@
    */
   public interface Comparator {
     
  -  public boolean compare(LoggingEvent event);
  +  /**
  +   * 
  +   * @param event
  +   * @return
  +   * @throws NullPointerException thrown if the lef or right side is null and 
  +   * the comparison operator is other than equals not equals ('=' or '!=').
  +   */
  +  public boolean compare(LoggingEvent event) throws NullPointerException;
   }
  
  
  
  1.4       +82 -56    logging-log4j/src/java/org/apache/log4j/lbel/comparator/StringComparator.java
  
  Index: StringComparator.java
  ===================================================================
  RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/lbel/comparator/StringComparator.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- StringComparator.java	1 Feb 2005 10:39:27 -0000	1.3
  +++ StringComparator.java	1 Feb 2005 14:46:21 -0000	1.4
  @@ -1,14 +1,25 @@
   /*
  - * Created on Jan 27, 2005
  + * Copyright 1999,2004 The Apache Software Foundation.
    *
  - * To change the template for this generated file go to
  - * Window>Preferences>Java>Code Generation>Code and Comments
  + * Licensed under the Apache License, Version 2.0 (the "License");
  + * you may not use this file except in compliance with the License.
  + * You may obtain a copy of the License at
  + *
  + *      http://www.apache.org/licenses/LICENSE-2.0
  + *
  + * Unless required by applicable law or agreed to in writing, software
  + * distributed under the License is distributed on an "AS IS" BASIS,
  + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  + * See the License for the specific language governing permissions and
  + * limitations under the License.
    */
  +
   package org.apache.log4j.lbel.comparator;
   
   import org.apache.log4j.lbel.Operator;
   import org.apache.log4j.lbel.ScanError;
   import org.apache.log4j.spi.LoggingEvent;
  +
   import org.apache.oro.text.regex.MalformedPatternException;
   import org.apache.oro.text.regex.Pattern;
   import org.apache.oro.text.regex.Perl5Compiler;
  @@ -16,102 +27,117 @@
   
   
   /**
  - * Base class for string-based comparators. 
  - * 
  - * <p>Allowed comparison operators are 'CHILDOF', '=', '!=', '>', '>=', '<', 
  + * Base class for string-based comparators.
  + *
  + * <p>Allowed comparison operators are 'CHILDOF', '=', '!=', '>', '>=', '<',
    * '<=', '~' and '!~' where '~' stands for regular expression match.
  - * 
  + *
    * @author <a href="http://www.qos.ch/log4j/">Ceki G&uuml;lc&uuml;</a>
    * @author Scott Deboy
    */
  -abstract public class StringComparator implements Comparator {
  -
  +public abstract class StringComparator implements Comparator {
     Operator operator;
     String rightSide;
     String rightSideWithDotSuffix;
     Pattern rightSidePattern;
     Perl5Matcher matcher;
   
  -  /**
  -   * Derived classes supply the left side of the comparison based on the event.
  -   * 
  -   * @param event
  -   * @return the left side of the expression
  -   */
  -  abstract protected String getLeftSide(LoggingEvent event);
  -  
  -  public StringComparator(Operator operator, String rightSide) throws ScanError  {
  +  public StringComparator(Operator operator, String rightSide)
  +    throws ScanError {
       this.operator = operator;
       this.rightSide = rightSide;
  -    
  -    
  -    if(operator.isRegex()) {
  +
  +    if (operator.isRegex()) {
         Perl5Compiler compiler = new Perl5Compiler();
         matcher = new Perl5Matcher();
         try {
           rightSidePattern = compiler.compile(rightSide);
  -      } catch(MalformedPatternException mfpe) {
  -        throw new ScanError("Malformed pattern ["+rightSide+"]", mfpe);
  +      } catch (MalformedPatternException mfpe) {
  +        throw new ScanError("Malformed pattern [" + rightSide + "]", mfpe);
         }
       }
  -    
  +
       // if CHILDOF operator and rightSide does not end with a dot add one
  -    if(operator.getCode() == Operator.CHILDOF && !rightSide.endsWith(".")) {
  +    if ((operator.getCode() == Operator.CHILDOF) && !rightSide.endsWith(".")) {
         this.rightSideWithDotSuffix = rightSide + ".";
       }
     }
  -  
   
  -  public boolean compare(LoggingEvent event) {
  -    
  +  /**
  +   * Derived classes supply the left side of the comparison based on the event.
  +   *
  +   * @param event
  +   * @return the left side of the expression
  +   */
  +  protected abstract String getLeftSide(LoggingEvent event);
  +
  +  public boolean compare(LoggingEvent event) throws NullPointerException {
       String leftSide = getLeftSide(event);
  -    
  -    if(leftSide == null) {
  -        switch(operator.getCode()) {
  -        case Operator.EQUAL: return leftSide == rightSide;   
  -        case Operator.NOT_EQUAL: return leftSide != rightSide;
  -        default: throw new NullPointerException("null leftside can only be used with == or != operators");
  -        }
  -      
  +
  +    if (leftSide == null) {
  +      switch (operator.getCode()) {
  +      case Operator.EQUAL:
  +        return leftSide == rightSide;
  +      case Operator.NOT_EQUAL:
  +        return leftSide != rightSide;
  +      default:
  +        throw new NullPointerException(
  +          "null leftside can only be used with == or != operators");
  +      }
       }
  -    
  -    if(operator.isRegex()) {
  +
  +    if (operator.isRegex()) {
         boolean match = matcher.contains(leftSide, rightSidePattern);
  -      if(operator.getCode() == Operator.REGEX_MATCH) {
  +      if (operator.getCode() == Operator.REGEX_MATCH) {
           return match;
         } else {
           return !match;
         }
       }
   
  -    if(operator.getCode() == Operator.CHILDOF) {
  -      if(leftSide.equals(rightSide)) {
  +    if (operator.getCode() == Operator.CHILDOF) {
  +      if (leftSide.equals(rightSide)) {
           return true;
         } else {
           return leftSide.startsWith(rightSideWithDotSuffix);
         }
       }
  -  
  +
  +    if (rightSide == null) {
  +      switch (operator.getCode()) {
  +      case Operator.EQUAL:
  +        return leftSide == rightSide;
  +      case Operator.NOT_EQUAL:
  +        return leftSide != rightSide;
  +      default:
  +        throw new NullPointerException(
  +          "null rightside can only be used with == or != operators");
  +      }
  +    }
       int compResult = leftSide.compareTo(rightSide);
  -    
  -    
  -    switch(operator.getCode()) {
  -    case Operator.EQUAL: return compResult == 0;   
  -    case Operator.NOT_EQUAL: return compResult != 0;      
  -    case Operator.GREATER: return compResult > 0;   
  -    case Operator.GREATER_OR_EQUAL: return compResult >= 0;   
  -    case Operator.LESS: return compResult < 0;   
  -    case Operator.LESS_OR_EQUAL: return compResult <= 0;    
  +
  +    switch (operator.getCode()) {
  +    case Operator.EQUAL: 
  +      return compResult == 0;
  +    case Operator.NOT_EQUAL:
  +      return compResult != 0;
  +    case Operator.GREATER:
  +      return compResult > 0;
  +    case Operator.GREATER_OR_EQUAL:
  +      return compResult >= 0;
  +    case Operator.LESS:
  +      return compResult < 0;
  +    case Operator.LESS_OR_EQUAL:
  +      return compResult <= 0;
       }
  -    
  -    throw new IllegalStateException("Unreachable state reached, operator "+operator);
  +
  +    throw new IllegalStateException(
  +      "Unreachable state reached, operator " + operator);
     }
   
  -  
     public String toString() {
       String full = this.getClass().getName();
       int i = full.lastIndexOf(".");
  -    return full.substring(i)+"("+operator+", "+rightSide+")";
  +    return full.substring(i) + "(" + operator + ", " + rightSide + ")";
     }
  -
   }
  
  
  
  1.6       +1 -0      logging-log4j/src/java/org/apache/log4j/lbel/Token.java
  
  Index: Token.java
  ===================================================================
  RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/lbel/Token.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- Token.java	1 Feb 2005 10:41:46 -0000	1.5
  +++ Token.java	1 Feb 2005 14:46:21 -0000	1.6
  @@ -27,6 +27,7 @@
     public static final int CLASS  = 170;
     public static final int METHOD = 180;
     public static final int NULL   = 190;
  +  public static final int DOT   = 200;
     
     public static final int EOF    = 1000;
   	
  
  
  
  1.10      +17 -1     logging-log4j/src/java/org/apache/log4j/lbel/Parser.java
  
  Index: Parser.java
  ===================================================================
  RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/lbel/Parser.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- Parser.java	1 Feb 2005 10:41:46 -0000	1.9
  +++ Parser.java	1 Feb 2005 14:46:21 -0000	1.10
  @@ -202,7 +202,8 @@
         ts.next();
         return new Node(Node.COMPARATOR, new TimestampComparator(operator, getLong()));
       case Token.PROPERTY:
  -      String key = (String) token.getValue();
  +      ts.next();
  +      String key = (String) getPropertyKey();
         ts.next();
         operator = getOperator();
         ts.next();
  @@ -279,4 +280,19 @@
         throw new ScanError("Expected a level stirng got "+levelStr);
       }
     }
  +  
  +  String getPropertyKey() throws IOException, ScanError {
  +    Token token = ts.getCurrent();
  +    if(token.getType() == Token.DOT) {
  +      ts.next();
  +      Token token2 = ts.getCurrent();
  +      if(token2.getType() == Token.LITERAL) {
  +        return (String) token2.getValue();
  +      } else {
  +        throw new ScanError("Expected LITERAL but got "+token2);
  +      }
  +    } else {
  +      throw new ScanError("Expected '.' but got "+token);
  +    }
  +  }
   }
  
  
  
  1.8       +59 -26    logging-log4j/src/java/org/apache/log4j/lbel/TokenStream.java
  
  Index: TokenStream.java
  ===================================================================
  RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/lbel/TokenStream.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- TokenStream.java	1 Feb 2005 10:41:46 -0000	1.7
  +++ TokenStream.java	1 Feb 2005 14:46:21 -0000	1.8
  @@ -44,6 +44,7 @@
       keywordMap.put("method", new Token(Token.METHOD, "method"));
       keywordMap.put("class", new Token(Token.CLASS, "class"));
       keywordMap.put("thread", new Token(Token.THREAD, "thread"));
  +    keywordMap.put("property", new Token(Token.PROPERTY, "property"));
       keywordMap.put("date", new Token(Token.DATE, "date"));
       keywordMap.put("null", new Token(Token.NULL, "null"));
     }
  @@ -51,11 +52,13 @@
     StreamTokenizer tokenizer;
   	int token;
     Token current;
  -	
  +	Reader reader;
     
     public TokenStream(Reader reader) {
  +    this.reader = reader;
     	tokenizer = new StreamTokenizer(reader);
     	tokenizer.resetSyntax();
  +    
     	tokenizer.whitespaceChars(' ', ' ');
     	tokenizer.whitespaceChars('\t', '\t');
     	tokenizer.whitespaceChars('\n', '\n');
  @@ -64,10 +67,15 @@
     	tokenizer.wordChars('a', 'z');
     	tokenizer.wordChars('A', 'Z');
     	tokenizer.wordChars('0', '9');
  +
  +
       
  -  	tokenizer.quoteChar('"');
  -  	tokenizer.quoteChar('\'');
  -  	tokenizer.parseNumbers();
  +    // StreamTokenizer does not correctly handle the '\' character within quotes
  +  	// tokenizer.quoteChar('"');
  +  	// tokenizer.quoteChar('\'');
  +  	
  +    tokenizer.parseNumbers();
  +    tokenizer.ordinaryChar('.');
     }
   
     public Token getCurrent() {
  @@ -90,22 +98,20 @@
     		case StreamTokenizer.TT_WORD:
     			String txt = tokenizer.sval;
           String lowerCaseTxt = txt.toLowerCase();
  -
  -        if(txt.startsWith("property.")) {
  -          current = extractPropertyToken(txt);  
  -        } else {
  -    		  Token result = (Token) keywordMap.get(lowerCaseTxt);
  -  		    if(result != null) {
  -  		  	  current = result;
  -  		    } else {
  -  		  	 current = new Token(Token.LITERAL, tokenizer.sval);
  -  		    }
  -        }
  +   		  Token result = (Token) keywordMap.get(lowerCaseTxt);
  + 		    if(result != null) {
  +  	  	  current = result;
  +  	    } else {
  +   	  	 current = new Token(Token.LITERAL, tokenizer.sval);
  +  	    }
           break;  		
     		case '"':
     	  case '\'':
  -  		  current = new Token(Token.LITERAL, tokenizer.sval);
  +  		  current = scanLiteral(token);
     		  break;
  +      case '.':
  +        current = new Token(Token.DOT, ".");
  +        break;
     		case '>':
      			token2 = tokenizer.nextToken();
     			if(token2 == '=') {
  @@ -153,15 +159,42 @@
     	}
     }
     
  -  Token extractPropertyToken(String txt) throws ScanError {
  -    int point = txt.indexOf('.');
  -    String key = txt.substring(point+1);
  -    // Is the key empty? (An empty key is the only thing that can go wrong at
  -    // this stage.
  -    if(key == null || key.length() == 0) {
  -      throw new ScanError("["+txt+"] has zero-legnth key.");
  -    } else {
  -      return new Token(Token.PROPERTY, key);
  -    }
  +  Token scanLiteral(int startChar) { 
  +   StringBuffer buf = new StringBuffer();
  +   try {
  +     int in = 0;
  +     while(in != -1) {
  +       in = reader.read();
  +       if(in == startChar) {
  +         break;
  +       } else {
  +           switch(in) {
  +           case '\n':
  +           case '\r':
  +             break; // ignore line breaks
  +           default: buf.append((char) in);
  +           }
  +       }
  +     }
  +   } catch(IOException io) {
  +   }
  +   
  +   return new Token(Token.LITERAL, buf.toString());
     }
  +  
  + // Token extractPropertyToken() throws ScanError {
  +//    int token = tokenizer.nextToken();
  +//    if(token == '.') {
  +//    }
  +//    
  +//    int point = txt.indexOf('.');
  +//    String key = txt.substring(point+1);
  +//    // Is the key empty? (An empty key is the only thing that can go wrong at
  +//    // this stage.
  +//    if(key == null || key.length() == 0) {
  +//      throw new ScanError("["+txt+"] has zero-legnth key.");
  +//    } else {
  +//      return new Token(Token.PROPERTY, key);
  +//    }
  + // }
   }
  
  
  
  1.3       +1 -1      logging-log4j/src/java/org/apache/log4j/lbel/EventEvaluator.java
  
  Index: EventEvaluator.java
  ===================================================================
  RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/lbel/EventEvaluator.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- EventEvaluator.java	1 Feb 2005 10:41:46 -0000	1.2
  +++ EventEvaluator.java	1 Feb 2005 14:46:21 -0000	1.3
  @@ -42,7 +42,7 @@
      * 
      * @param event The event to evaluate
      * @return true if there is a match, false otherwise. 
  -   * @throws NullPointerException thrown if lefthand side is null
  +   * @throws NullPointerException can be thrown in presence of null values
      */
     boolean evaluate(LoggingEvent event) throws NullPointerException;
   }
  
  
  
  1.6       +14 -10    logging-log4j/tests/src/java/org/apache/log4j/lbel/EventEvaluationTest.java
  
  Index: EventEvaluationTest.java
  ===================================================================
  RCS file: /home/cvs/logging-log4j/tests/src/java/org/apache/log4j/lbel/EventEvaluationTest.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- EventEvaluationTest.java	1 Feb 2005 10:39:27 -0000	1.5
  +++ EventEvaluationTest.java	1 Feb 2005 14:46:21 -0000	1.6
  @@ -93,10 +93,11 @@
       evaluator = new LBELEventEvaluator("message ~ 'h[a-z]* world'");
       assertTrue(evaluator.evaluate(event));
   
  -    // the following test cannot be run because of a bug in the way 
  -    // java.io.StreamTokenizer incorrectly interprets the '\' character within quotes
  -    // evaluator = new LBELEventEvaluator("message ~ 'h\\w* world'");
  -    //assertTrue(evaluator.evaluate(event));
  +    evaluator = new LBELEventEvaluator("message ~ 'h\\w* world'");
  +    assertTrue(evaluator.evaluate(event));
  +
  +    evaluator = new LBELEventEvaluator("message ~ 'hello\\sworld'");
  +    assertTrue(evaluator.evaluate(event));
   
       LBELEventEvaluator evaluator = new LBELEventEvaluator("message !~ 'x'");
       assertTrue(evaluator.evaluate(event));
  @@ -106,19 +107,19 @@
     }
     
     public void testLogger() throws Exception, ScanError {
  -    evaluator = new LBELEventEvaluator("logger = org.wombat");
  +    evaluator = new LBELEventEvaluator("logger = 'org.wombat'");
       assertTrue(evaluator.evaluate(event));
       
  -    evaluator = new LBELEventEvaluator("logger = org.wombat.x");
  +    evaluator = new LBELEventEvaluator("logger = 'org.wombat.x'");
       assertTrue(!evaluator.evaluate(event));
       
  -    evaluator = new LBELEventEvaluator("logger != org.wombat.x");
  +    evaluator = new LBELEventEvaluator("logger != 'org.wombat.x'");
       assertTrue(evaluator.evaluate(event));
       
  -    evaluator = new LBELEventEvaluator("logger < org.wombat.x");
  +    evaluator = new LBELEventEvaluator("logger < 'org.wombat.x'");
       assertTrue(evaluator.evaluate(event));
   
  -    evaluator = new LBELEventEvaluator("logger <= org.wombat.x");
  +    evaluator = new LBELEventEvaluator("logger <= 'org.wombat.x'");
       assertTrue(evaluator.evaluate(event));
   
       evaluator = new LBELEventEvaluator("logger > org");
  @@ -163,7 +164,7 @@
     }
   
     public void testClass() throws ScanError {
  -    evaluator = new LBELEventEvaluator("class = org.wombat");
  +    evaluator = new LBELEventEvaluator("class = 'org.wombat'");
       assertTrue(evaluator.evaluate(event));
       
       evaluator = new LBELEventEvaluator("class > org");
  @@ -180,6 +181,9 @@
       evaluator = new LBELEventEvaluator("message != NULL");
       assertTrue(!evaluator.evaluate(nullEvent));
   
  +    evaluator = new LBELEventEvaluator("message != NULL");
  +    assertTrue(evaluator.evaluate(event));
  +
       try {
         evaluator = new LBELEventEvaluator("message > NULL");
         assertTrue(evaluator.evaluate(nullEvent));
  
  
  
  1.5       +24 -13    logging-log4j/tests/src/java/org/apache/log4j/lbel/TokenStreamTest.java
  
  Index: TokenStreamTest.java
  ===================================================================
  RCS file: /home/cvs/logging-log4j/tests/src/java/org/apache/log4j/lbel/TokenStreamTest.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- TokenStreamTest.java	31 Jan 2005 20:31:09 -0000	1.4
  +++ TokenStreamTest.java	1 Feb 2005 14:46:21 -0000	1.5
  @@ -241,28 +241,39 @@
   
       ts.next(); t = ts.getCurrent();
       assertEquals(Token.PROPERTY, t.getType());
  +    ts.next(); t = ts.getCurrent();
  +    assertEquals(Token.DOT, t.getType());
  +    ts.next(); t = ts.getCurrent();
  +    assertEquals(Token.LITERAL, t.getType());
       assertEquals("x", t.getValue());
   
       ts.next(); t = ts.getCurrent();
       assertEquals(Token.PROPERTY, t.getType());
  +    ts.next(); t = ts.getCurrent();
  +    assertEquals(Token.DOT, t.getType());
  +    ts.next(); t = ts.getCurrent();
  +    assertEquals(Token.LITERAL, t.getType());
       assertEquals("xyz", t.getValue());
  +
  +    ts.next(); t = ts.getCurrent();
  +    assertEquals(Token.PROPERTY, t.getType());
  +    ts.next(); t = ts.getCurrent();
  +    assertEquals(Token.DOT, t.getType());
       
  -    try {
  -      ts.next();
  -      fail("A ScanError should have been thrown");
  -    } catch(ScanError e) {
  -    }
     }
   
     
  -  public void testProperty2() throws IOException, ScanError {
  -    // TODO: add support for spaces in prooperty keys
  +  public void testQuotedProperty() throws IOException, ScanError {
       
  -//    StringReader sr = new StringReader(" property.'toto a' etc");
  -//    TokenStream ts = new TokenStream(sr);
  -//
  -//    ts.next(); t = ts.getCurrent();
  -//    assertEquals(Token.PROPERTY, t.getType());
  -//    assertEquals("toto a", t.getValue());
  +    StringReader sr = new StringReader(" property.'toto a' etc");
  +    TokenStream ts = new TokenStream(sr);
  +
  +    ts.next(); t = ts.getCurrent();
  +    assertEquals(Token.PROPERTY, t.getType());
  +    ts.next(); t = ts.getCurrent();
  +    assertEquals(Token.DOT, t.getType());
  +    ts.next(); t = ts.getCurrent();
  +    assertEquals(Token.LITERAL, t.getType());
  +    assertEquals("toto a", t.getValue());
     }
   }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org