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 ca...@apache.org on 2006/03/08 07:14:47 UTC

svn commit: r384131 - in /logging/log4j/trunk: src/java/org/apache/log4j/ src/java/org/apache/log4j/helpers/ src/java/org/apache/log4j/pattern/ tests/input/pattern/ tests/src/java/org/apache/log4j/ tests/witness/pattern/

Author: carnold
Date: Tue Mar  7 22:14:45 2006
New Revision: 384131

URL: http://svn.apache.org/viewcvs?rev=384131&view=rev
Log:
Bug 38024: Restored PatternLayout.createPatternLayout for log4j 1.2 compat

Added:
    logging/log4j/trunk/src/java/org/apache/log4j/helpers/FormattingInfo.java
    logging/log4j/trunk/src/java/org/apache/log4j/helpers/PatternConverter.java
    logging/log4j/trunk/src/java/org/apache/log4j/helpers/PatternParser.java
    logging/log4j/trunk/src/java/org/apache/log4j/pattern/BridgePatternConverter.java
    logging/log4j/trunk/src/java/org/apache/log4j/pattern/BridgePatternParser.java
    logging/log4j/trunk/tests/input/pattern/patternLayout15.properties
    logging/log4j/trunk/tests/src/java/org/apache/log4j/MyPatternLayout.java
    logging/log4j/trunk/tests/src/java/org/apache/log4j/MyPatternParser.java
    logging/log4j/trunk/tests/witness/pattern/patternLayout.15
Modified:
    logging/log4j/trunk/src/java/org/apache/log4j/PatternLayout.java
    logging/log4j/trunk/tests/src/java/org/apache/log4j/PatternLayoutTestCase.java

Modified: logging/log4j/trunk/src/java/org/apache/log4j/PatternLayout.java
URL: http://svn.apache.org/viewcvs/logging/log4j/trunk/src/java/org/apache/log4j/PatternLayout.java?rev=384131&r1=384130&r2=384131&view=diff
==============================================================================
--- logging/log4j/trunk/src/java/org/apache/log4j/PatternLayout.java (original)
+++ logging/log4j/trunk/src/java/org/apache/log4j/PatternLayout.java Tue Mar  7 22:14:45 2006
@@ -17,18 +17,9 @@
 package org.apache.log4j;
 
 import org.apache.log4j.helpers.OptionConverter;
-import org.apache.log4j.pattern.FormattingInfo;
-import org.apache.log4j.pattern.LiteralPatternConverter;
-import org.apache.log4j.pattern.LoggingEventPatternConverter;
-import org.apache.log4j.pattern.PatternParser;
+import org.apache.log4j.helpers.PatternConverter;
+import org.apache.log4j.pattern.BridgePatternConverter;
 import org.apache.log4j.spi.LoggingEvent;
-import org.apache.log4j.spi.LoggerRepositoryEx;
-
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
 
 
 // Contributors:   Nelson Minar <ne...@monkey.org>
@@ -439,25 +430,16 @@
    */
   public static final String PATTERN_RULE_REGISTRY = "PATTERN_RULE_REGISTRY";
 
-  /**
-   * Conversion pattern.
-   */
-  private String conversionPattern;
-
-  /**
-   * Pattern converters.
-   */
-  private LoggingEventPatternConverter[] patternConverters;
 
   /**
-   * Field widths and alignment corresponding to pattern converters.
-   */
-  private FormattingInfo[] patternFields;
+    *  Initial converter for pattern.
+    */
+  private PatternConverter head;
 
   /**
-   * String buffer used in formatting.
+   * Conversion pattern.
    */
-  private StringBuffer buf = new StringBuffer();
+  private String conversionPattern;
 
   /**
    * True if any element in pattern formats information from exceptions.
@@ -477,9 +459,15 @@
     * Constructs a PatternLayout using the supplied conversion pattern.
    * @param pattern conversion pattern.
   */
-  public PatternLayout(String pattern) {
+  public PatternLayout(final String pattern) {
     this.conversionPattern = pattern;
-    activateOptions();
+    head = createPatternParser(
+            (pattern == null) ? DEFAULT_CONVERSION_PATTERN : pattern).parse();
+    if (head instanceof BridgePatternConverter) {
+        handlesExceptions = !((BridgePatternConverter) head).ignoresThrowable();
+    } else {
+        handlesExceptions = false;
+    }
   }
 
   /**
@@ -489,9 +477,15 @@
    *
    * @param conversionPattern conversion pattern.
   */
-  public void setConversionPattern(String conversionPattern) {
+  public void setConversionPattern(final String conversionPattern) {
     this.conversionPattern =
       OptionConverter.convertSpecialChars(conversionPattern);
+      head = createPatternParser(this.conversionPattern).parse();
+      if (head instanceof BridgePatternConverter) {
+          handlesExceptions = !((BridgePatternConverter) head).ignoresThrowable();
+      } else {
+          handlesExceptions = false;
+      }
   }
 
   /**
@@ -502,69 +496,41 @@
     return conversionPattern;
   }
 
+
+    /**
+      Returns PatternParser used to parse the conversion string. Subclasses
+      may override this to return a subclass of PatternParser which recognize
+      custom conversion characters.
+
+      @since 0.9.0
+    */
+    protected org.apache.log4j.helpers.PatternParser createPatternParser(String pattern) {
+      return new org.apache.log4j.pattern.BridgePatternParser(pattern,
+              repository, getLogger());
+    }
+
+
   /**
     Activates the conversion pattern. Do not forget to call this method after
     you change the parameters of the PatternLayout instance.
   */
   public void activateOptions() {
-    List converters = new ArrayList();
-    List fields = new ArrayList();
-    Map converterRegistry = null;
-
-    if (this.repository != null) {
-      if (repository instanceof LoggerRepositoryEx) {
-        converterRegistry =
-            (Map) ((LoggerRepositoryEx) repository).getObject(PATTERN_RULE_REGISTRY);
-      }
-    }
-
-    PatternParser.parse(
-      conversionPattern, converters, fields, converterRegistry,
-      PatternParser.getPatternLayoutRules(), getLogger());
-
-    patternConverters = new LoggingEventPatternConverter[converters.size()];
-    patternFields = new FormattingInfo[converters.size()];
-
-    int i = 0;
-    Iterator converterIter = converters.iterator();
-    Iterator fieldIter = fields.iterator();
-
-    while (converterIter.hasNext()) {
-      Object converter = converterIter.next();
-
-      if (converter instanceof LoggingEventPatternConverter) {
-        patternConverters[i] = (LoggingEventPatternConverter) converter;
-        handlesExceptions |= patternConverters[i].handlesThrowable();
-      } else {
-        patternConverters[i] = new LiteralPatternConverter("");
-      }
-
-      if (fieldIter.hasNext()) {
-        patternFields[i] = (FormattingInfo) fieldIter.next();
-      } else {
-        patternFields[i] = FormattingInfo.getDefault();
-      }
-
-      i++;
-    }
+      // nothing to do.
   }
 
+
   /**
    *  Formats a logging event to a writer.
    * @param event logging event to be formatted.
   */
   public String format(final LoggingEvent event) {
-    buf.setLength(0);
-
-    for (int i = 0; i < patternConverters.length; i++) {
-      int startField = buf.length();
-      patternConverters[i].format(event, buf);
-      patternFields[i].format(startField, buf);
-    }
-
-    String retval = buf.toString();
-    buf.setLength(0);
-    return retval;
+      StringBuffer buf = new StringBuffer();
+      for(PatternConverter c = head;
+          c != null;
+          c = c.next) {
+          c.format(buf, event);
+      }
+      return buf.toString();
   }
 
   /**

Added: logging/log4j/trunk/src/java/org/apache/log4j/helpers/FormattingInfo.java
URL: http://svn.apache.org/viewcvs/logging/log4j/trunk/src/java/org/apache/log4j/helpers/FormattingInfo.java?rev=384131&view=auto
==============================================================================
--- logging/log4j/trunk/src/java/org/apache/log4j/helpers/FormattingInfo.java (added)
+++ logging/log4j/trunk/src/java/org/apache/log4j/helpers/FormattingInfo.java Tue Mar  7 22:14:45 2006
@@ -0,0 +1,45 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ * 
+ * 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.helpers;
+
+
+/**
+   FormattingInfo instances contain the information obtained when parsing
+   formatting modifiers in conversion modifiers.
+
+   @author <a href=mailto:jim_cakalic@na.biomerieux.com>Jim Cakalic</a>
+   @author Ceki G&uuml;lc&uuml;
+
+   @since 0.8.2
+   @deprecated Since 1.3
+ */
+public class FormattingInfo {
+  int min = -1;
+  int max = Integer.MAX_VALUE;
+  boolean leftAlign = false;
+
+  void reset() {
+    min = -1;
+    max = Integer.MAX_VALUE;
+    leftAlign = false;      
+  }
+
+  void dump() {
+    LogLog.debug("min="+min+", max="+max+", leftAlign="+leftAlign);
+  }
+}
+ 

Added: logging/log4j/trunk/src/java/org/apache/log4j/helpers/PatternConverter.java
URL: http://svn.apache.org/viewcvs/logging/log4j/trunk/src/java/org/apache/log4j/helpers/PatternConverter.java?rev=384131&view=auto
==============================================================================
--- logging/log4j/trunk/src/java/org/apache/log4j/helpers/PatternConverter.java (added)
+++ logging/log4j/trunk/src/java/org/apache/log4j/helpers/PatternConverter.java Tue Mar  7 22:14:45 2006
@@ -0,0 +1,111 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ * 
+ * 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.helpers;
+
+import org.apache.log4j.spi.LoggingEvent;
+
+/**
+
+   <p>PatternConverter is an abtract class that provides the
+   formatting functionality that derived classes need.
+
+   <p>Conversion specifiers in a conversion patterns are parsed to
+   individual PatternConverters. Each of which is responsible for
+   converting a logging event in a converter specific manner.
+
+   @author <a href="mailto:cakalijp@Maritz.com">James P. Cakalic</a>
+   @author Ceki G&uuml;lc&uuml;
+
+   @since 0.8.2
+   @deprecated Since 1.3
+ */
+public abstract class PatternConverter {
+  public PatternConverter next;
+  int min = -1;
+  int max = Integer.MAX_VALUE;
+  boolean leftAlign = false;
+
+  protected
+  PatternConverter() {  }
+  
+  protected
+  PatternConverter(FormattingInfo fi) {
+    min = fi.min;
+    max = fi.max;
+    leftAlign = fi.leftAlign;
+  }
+
+  /**
+     Derived pattern converters must override this method in order to
+     convert conversion specifiers in the correct way.
+  */
+  abstract
+  protected
+  String convert(LoggingEvent event);
+
+  /**
+     A template method for formatting in a converter specific way.
+   */
+  public
+  void format(StringBuffer sbuf, LoggingEvent e) {
+    String s = convert(e);
+
+    if(s == null) {
+      if(0 < min)
+	spacePad(sbuf, min);
+      return;
+    }
+
+    int len = s.length();
+
+    if(len > max)
+      sbuf.append(s.substring(len-max));
+    else if(len < min) {
+      if(leftAlign) {	
+	sbuf.append(s);
+	spacePad(sbuf, min-len);
+      }
+      else {
+	spacePad(sbuf, min-len);
+	sbuf.append(s);
+      }
+    }
+    else
+      sbuf.append(s);
+  }	
+
+  static String[] SPACES = {" ", "  ", "    ", "        ", //1,2,4,8 spaces
+			    "                ", // 16 spaces
+			    "                                " }; // 32 spaces
+
+  /**
+     Fast space padding method.
+  */
+  public
+  void spacePad(StringBuffer sbuf, int length) {
+    while(length >= 32) {
+      sbuf.append(SPACES[5]);
+      length -= 32;
+    }
+    
+    for(int i = 4; i >= 0; i--) {	
+      if((length & (1<<i)) != 0) {
+	sbuf.append(SPACES[i]);
+      }
+    }
+  }
+}

Added: logging/log4j/trunk/src/java/org/apache/log4j/helpers/PatternParser.java
URL: http://svn.apache.org/viewcvs/logging/log4j/trunk/src/java/org/apache/log4j/helpers/PatternParser.java?rev=384131&view=auto
==============================================================================
--- logging/log4j/trunk/src/java/org/apache/log4j/helpers/PatternParser.java (added)
+++ logging/log4j/trunk/src/java/org/apache/log4j/helpers/PatternParser.java Tue Mar  7 22:14:45 2006
@@ -0,0 +1,552 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ * 
+ * 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.helpers;
+
+import org.apache.log4j.Layout;
+import org.apache.log4j.spi.LocationInfo;
+import org.apache.log4j.spi.LoggingEvent;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+// Contributors:   Nelson Minar <(n...@monkey.org>
+//                 Igor E. Poteryaev <ja...@mail.ru>
+//                 Reinhard Deschler <re...@web.de>
+
+/**
+   Most of the work of the {@link org.apache.log4j.PatternLayout} class
+   is delegated to the PatternParser class.
+
+   <p>It is this class that parses conversion patterns and creates
+   a chained list of {@link OptionConverter OptionConverters}.
+
+   @author <a href=mailto:"cakalijp@Maritz.com">James P. Cakalic</a>
+   @author Ceki G&uuml;lc&uuml;
+   @author Anders Kristensen
+
+   @since 0.8.2
+   @deprecated Since 1.3
+*/
+public class PatternParser {
+
+  private static final char ESCAPE_CHAR = '%';
+
+  private static final int LITERAL_STATE = 0;
+  private static final int CONVERTER_STATE = 1;
+  private static final int MINUS_STATE = 2;
+  private static final int DOT_STATE = 3;
+  private static final int MIN_STATE = 4;
+  private static final int MAX_STATE = 5;
+
+  static final int FULL_LOCATION_CONVERTER = 1000;
+  static final int METHOD_LOCATION_CONVERTER = 1001;
+  static final int CLASS_LOCATION_CONVERTER = 1002;
+  static final int LINE_LOCATION_CONVERTER = 1003;
+  static final int FILE_LOCATION_CONVERTER = 1004;
+
+  static final int RELATIVE_TIME_CONVERTER = 2000;
+  static final int THREAD_CONVERTER = 2001;
+  static final int LEVEL_CONVERTER = 2002;
+  static final int NDC_CONVERTER = 2003;
+  static final int MESSAGE_CONVERTER = 2004;
+
+  int state;
+  protected StringBuffer currentLiteral = new StringBuffer(32);
+  protected int patternLength;
+  protected int i;
+  PatternConverter head;
+  PatternConverter tail;
+  protected FormattingInfo formattingInfo = new FormattingInfo();
+  protected String pattern;
+
+  public
+  PatternParser(String pattern) {
+    this.pattern = pattern;
+    patternLength =  pattern.length();
+    state = LITERAL_STATE;
+  }
+
+  private
+  void  addToList(PatternConverter pc) {
+    if(head == null) {
+      head = tail = pc;
+    } else {
+      tail.next = pc;
+      tail = pc;
+    }
+  }
+
+  protected
+  String extractOption() {
+    if((i < patternLength) && (pattern.charAt(i) == '{')) {
+      int end = pattern.indexOf('}', i);
+      if (end > i) {
+	String r = pattern.substring(i + 1, end);
+	i = end+1;
+	return r;
+      }
+    }
+    return null;
+  }
+
+
+  /**
+     The option is expected to be in decimal and positive. In case of
+     error, zero is returned.  */
+  protected
+  int extractPrecisionOption() {
+    String opt = extractOption();
+    int r = 0;
+    if(opt != null) {
+      try {
+	r = Integer.parseInt(opt);
+	if(r <= 0) {
+	    LogLog.error(
+	        "Precision option (" + opt + ") isn't a positive integer.");
+	    r = 0;
+	}
+      }
+      catch (NumberFormatException e) {
+	LogLog.error("Category option \""+opt+"\" not a decimal integer.", e);
+      }
+    }
+    return r;
+  }
+
+  public
+  PatternConverter parse() {
+    char c;
+    i = 0;
+    while(i < patternLength) {
+      c = pattern.charAt(i++);
+      switch(state) {
+      case LITERAL_STATE:
+        // In literal state, the last char is always a literal.
+        if(i == patternLength) {
+          currentLiteral.append(c);
+          continue;
+        }
+        if(c == ESCAPE_CHAR) {
+          // peek at the next char.
+          switch(pattern.charAt(i)) {
+          case ESCAPE_CHAR:
+            currentLiteral.append(c);
+            i++; // move pointer
+            break;
+          case 'n':
+            currentLiteral.append(Layout.LINE_SEP);
+            i++; // move pointer
+            break;
+          default:
+            if(currentLiteral.length() != 0) {
+              addToList(new LiteralPatternConverter(
+                                                  currentLiteral.toString()));
+              //LogLog.debug("Parsed LITERAL converter: \""
+              //           +currentLiteral+"\".");
+            }
+            currentLiteral.setLength(0);
+            currentLiteral.append(c); // append %
+            state = CONVERTER_STATE;
+            formattingInfo.reset();
+          }
+        }
+        else {
+          currentLiteral.append(c);
+        }
+        break;
+      case CONVERTER_STATE:
+	currentLiteral.append(c);
+	switch(c) {
+	case '-':
+	  formattingInfo.leftAlign = true;
+	  break;
+	case '.':
+	  state = DOT_STATE;
+	  break;
+	default:
+	  if(c >= '0' && c <= '9') {
+	    formattingInfo.min = c - '0';
+	    state = MIN_STATE;
+	  }
+	  else
+	    finalizeConverter(c);
+	} // switch
+	break;
+      case MIN_STATE:
+	currentLiteral.append(c);
+	if(c >= '0' && c <= '9')
+	  formattingInfo.min = formattingInfo.min*10 + (c - '0');
+	else if(c == '.')
+	  state = DOT_STATE;
+	else {
+	  finalizeConverter(c);
+	}
+	break;
+      case DOT_STATE:
+	currentLiteral.append(c);
+	if(c >= '0' && c <= '9') {
+	  formattingInfo.max = c - '0';
+	   state = MAX_STATE;
+	}
+	else {
+	  LogLog.error("Error occured in position "+i
+		     +".\n Was expecting digit, instead got char \""+c+"\".");
+	  state = LITERAL_STATE;
+	}
+	break;
+      case MAX_STATE:
+	currentLiteral.append(c);
+	if(c >= '0' && c <= '9')
+	  formattingInfo.max = formattingInfo.max*10 + (c - '0');
+	else {
+	  finalizeConverter(c);
+	  state = LITERAL_STATE;
+	}
+	break;
+      } // switch
+    } // while
+    if(currentLiteral.length() != 0) {
+      addToList(new LiteralPatternConverter(currentLiteral.toString()));
+      //LogLog.debug("Parsed LITERAL converter: \""+currentLiteral+"\".");
+    }
+    return head;
+  }
+
+  protected
+  void finalizeConverter(char c) {
+    PatternConverter pc = null;
+    switch(c) {
+    case 'c':
+      pc = new CategoryPatternConverter(formattingInfo,
+					extractPrecisionOption());
+      //LogLog.debug("CATEGORY converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'C':
+      pc = new ClassNamePatternConverter(formattingInfo,
+					 extractPrecisionOption());
+      //LogLog.debug("CLASS_NAME converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'd':
+      String dateFormatStr = AbsoluteTimeDateFormat.ISO8601_DATE_FORMAT;
+      DateFormat df;
+      String dOpt = extractOption();
+      if(dOpt != null)
+	dateFormatStr = dOpt;
+
+      if(dateFormatStr.equalsIgnoreCase(
+                                    AbsoluteTimeDateFormat.ISO8601_DATE_FORMAT))
+	df = new  ISO8601DateFormat();
+      else if(dateFormatStr.equalsIgnoreCase(
+                                   AbsoluteTimeDateFormat.ABS_TIME_DATE_FORMAT))
+	df = new AbsoluteTimeDateFormat();
+      else if(dateFormatStr.equalsIgnoreCase(
+                              AbsoluteTimeDateFormat.DATE_AND_TIME_DATE_FORMAT))
+	df = new DateTimeDateFormat();
+      else {
+	try {
+	  df = new SimpleDateFormat(dateFormatStr);
+	}
+	catch (IllegalArgumentException e) {
+	  LogLog.error("Could not instantiate SimpleDateFormat with " +
+		       dateFormatStr, e);
+	  df = (DateFormat) OptionConverter.instantiateByClassName(
+			           "org.apache.log4j.helpers.ISO8601DateFormat",
+				   DateFormat.class, null);
+	}
+      }
+      pc = new DatePatternConverter(formattingInfo, df);
+      //LogLog.debug("DATE converter {"+dateFormatStr+"}.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'F':
+      pc = new LocationPatternConverter(formattingInfo,
+					FILE_LOCATION_CONVERTER);
+      //LogLog.debug("File name converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'l':
+      pc = new LocationPatternConverter(formattingInfo,
+					FULL_LOCATION_CONVERTER);
+      //LogLog.debug("Location converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'L':
+      pc = new LocationPatternConverter(formattingInfo,
+					LINE_LOCATION_CONVERTER);
+      //LogLog.debug("LINE NUMBER converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'm':
+      pc = new BasicPatternConverter(formattingInfo, MESSAGE_CONVERTER);
+      //LogLog.debug("MESSAGE converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'M':
+      pc = new LocationPatternConverter(formattingInfo,
+					METHOD_LOCATION_CONVERTER);
+      //LogLog.debug("METHOD converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'p':
+      pc = new BasicPatternConverter(formattingInfo, LEVEL_CONVERTER);
+      //LogLog.debug("LEVEL converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'r':
+      pc = new BasicPatternConverter(formattingInfo,
+					 RELATIVE_TIME_CONVERTER);
+      //LogLog.debug("RELATIVE time converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 't':
+      pc = new BasicPatternConverter(formattingInfo, THREAD_CONVERTER);
+      //LogLog.debug("THREAD converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+      /*case 'u':
+      if(i < patternLength) {
+	char cNext = pattern.charAt(i);
+	if(cNext >= '0' && cNext <= '9') {
+	  pc = new UserFieldPatternConverter(formattingInfo, cNext - '0');
+	  LogLog.debug("USER converter ["+cNext+"].");
+	  formattingInfo.dump();
+	  currentLiteral.setLength(0);
+	  i++;
+	}
+	else
+	  LogLog.error("Unexpected char" +cNext+" at position "+i);
+      }
+      break;*/
+    case 'x':
+      pc = new BasicPatternConverter(formattingInfo, NDC_CONVERTER);
+      //LogLog.debug("NDC converter.");
+      currentLiteral.setLength(0);
+      break;
+    case 'X':
+      String xOpt = extractOption();
+      pc = new MDCPatternConverter(formattingInfo, xOpt);
+      currentLiteral.setLength(0);
+      break;
+    default:
+      LogLog.error("Unexpected char [" +c+"] at position "+i
+		   +" in conversion patterrn.");
+      pc = new LiteralPatternConverter(currentLiteral.toString());
+      currentLiteral.setLength(0);
+    }
+
+    addConverter(pc);
+  }
+
+  protected
+  void addConverter(PatternConverter pc) {
+    currentLiteral.setLength(0);
+    // Add the pattern converter to the list.
+    addToList(pc);
+    // Next pattern is assumed to be a literal.
+    state = LITERAL_STATE;
+    // Reset formatting info
+    formattingInfo.reset();
+  }
+
+  // ---------------------------------------------------------------------
+  //                      PatternConverters
+  // ---------------------------------------------------------------------
+
+  private static class BasicPatternConverter extends PatternConverter {
+    int type;
+
+    BasicPatternConverter(FormattingInfo formattingInfo, int type) {
+      super(formattingInfo);
+      this.type = type;
+    }
+
+    public
+    String convert(LoggingEvent event) {
+      switch(type) {
+      case RELATIVE_TIME_CONVERTER:
+	return (Long.toString(event.timeStamp - LoggingEvent.getStartTime()));
+      case THREAD_CONVERTER:
+	return event.getThreadName();
+      case LEVEL_CONVERTER:
+	return event.getLevel().toString();
+      case NDC_CONVERTER:
+	return event.getNDC();
+      case MESSAGE_CONVERTER: {
+	return event.getRenderedMessage();
+      }
+      default: return null;
+      }
+    }
+  }
+
+  private static class LiteralPatternConverter extends PatternConverter {
+    private String literal;
+
+    LiteralPatternConverter(String value) {
+      literal = value;
+    }
+
+    public
+    final
+    void format(StringBuffer sbuf, LoggingEvent event) {
+      sbuf.append(literal);
+    }
+
+    public
+    String convert(LoggingEvent event) {
+      return literal;
+    }
+  }
+
+  private static class DatePatternConverter extends PatternConverter {
+    private DateFormat df;
+    private Date date;
+
+    DatePatternConverter(FormattingInfo formattingInfo, DateFormat df) {
+      super(formattingInfo);
+      date = new Date();
+      this.df = df;
+    }
+
+    public
+    String convert(LoggingEvent event) {
+      date.setTime(event.timeStamp);
+      String converted = null;
+      try {
+        converted = df.format(date);
+      }
+      catch (Exception ex) {
+        LogLog.error("Error occured while converting date.", ex);
+      }
+      return converted;
+    }
+  }
+
+  private static class MDCPatternConverter extends PatternConverter {
+    private String key;
+
+    MDCPatternConverter(FormattingInfo formattingInfo, String key) {
+      super(formattingInfo);
+      this.key = key;
+    }
+
+    public
+    String convert(LoggingEvent event) {
+      Object val = event.getMDC(key);
+      if(val == null) {
+	return null;
+      } else {
+	return val.toString();
+      }
+    }
+  }
+
+
+  private class LocationPatternConverter extends PatternConverter {
+    int type;
+
+    LocationPatternConverter(FormattingInfo formattingInfo, int type) {
+      super(formattingInfo);
+      this.type = type;
+    }
+
+    public
+    String convert(LoggingEvent event) {
+      LocationInfo locationInfo = event.getLocationInformation();
+      switch(type) {
+      case FULL_LOCATION_CONVERTER:
+	return locationInfo.fullInfo;
+      case METHOD_LOCATION_CONVERTER:
+	return locationInfo.getMethodName();
+      case LINE_LOCATION_CONVERTER:
+	return locationInfo.getLineNumber();
+      case FILE_LOCATION_CONVERTER:
+	return locationInfo.getFileName();
+      default: return null;
+      }
+    }
+  }
+
+  private static abstract class NamedPatternConverter extends PatternConverter {
+    int precision;
+
+    NamedPatternConverter(FormattingInfo formattingInfo, int precision) {
+      super(formattingInfo);
+      this.precision =  precision;
+    }
+
+    abstract
+    String getFullyQualifiedName(LoggingEvent event);
+
+    public
+    String convert(LoggingEvent event) {
+      String n = getFullyQualifiedName(event);
+      if(precision <= 0)
+	return n;
+      else {
+	int len = n.length();
+
+	// We substract 1 from 'len' when assigning to 'end' to avoid out of
+	// bounds exception in return r.substring(end+1, len). This can happen if
+	// precision is 1 and the category name ends with a dot.
+	int end = len -1 ;
+	for(int i = precision; i > 0; i--) {
+	  end = n.lastIndexOf('.', end-1);
+	  if(end == -1)
+	    return n;
+	}
+	return n.substring(end+1, len);
+      }
+    }
+  }
+
+  private class ClassNamePatternConverter extends NamedPatternConverter {
+
+    ClassNamePatternConverter(FormattingInfo formattingInfo, int precision) {
+      super(formattingInfo, precision);
+    }
+
+    String getFullyQualifiedName(LoggingEvent event) {
+      return event.getLocationInformation().getClassName();
+    }
+  }
+
+  private class CategoryPatternConverter extends NamedPatternConverter {
+
+    CategoryPatternConverter(FormattingInfo formattingInfo, int precision) {
+      super(formattingInfo, precision);
+    }
+
+    String getFullyQualifiedName(LoggingEvent event) {
+      return event.getLoggerName();
+    }
+  }
+}
+

Added: logging/log4j/trunk/src/java/org/apache/log4j/pattern/BridgePatternConverter.java
URL: http://svn.apache.org/viewcvs/logging/log4j/trunk/src/java/org/apache/log4j/pattern/BridgePatternConverter.java?rev=384131&view=auto
==============================================================================
--- logging/log4j/trunk/src/java/org/apache/log4j/pattern/BridgePatternConverter.java (added)
+++ logging/log4j/trunk/src/java/org/apache/log4j/pattern/BridgePatternConverter.java Tue Mar  7 22:14:45 2006
@@ -0,0 +1,145 @@
+/*
+ * Copyright 1999,2005 The Apache Software Foundation.
+ *
+ * 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.pattern;
+
+import org.apache.log4j.PatternLayout;
+import org.apache.log4j.ULogger;
+import org.apache.log4j.spi.LoggerRepository;
+import org.apache.log4j.spi.LoggerRepositoryEx;
+import org.apache.log4j.spi.LoggingEvent;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * The class implements the pre log4j 1.3 org.apache.log4j.helpers.PatternConverter
+ * contract by delegating to the log4j 1.3 pattern implementation.
+ *
+ *
+ * @author Curt Arnold
+ * @since 1.3
+ *
+ */
+public final class BridgePatternConverter
+  extends org.apache.log4j.helpers.PatternConverter {
+  /**
+   * Pattern converters.
+   */
+  private LoggingEventPatternConverter[] patternConverters;
+
+  /**
+   * Field widths and alignment corresponding to pattern converters.
+   */
+  private FormattingInfo[] patternFields;
+
+  /**
+   * Does pattern process exceptions.
+   */
+  private boolean handlesExceptions;
+
+  /**
+   * Create a new instance.
+   * @param pattern pattern, may not be null.
+   * @param repository logger repository, may be null.
+   * @param logger logger for internal logging.
+   */
+  public BridgePatternConverter(
+    final String pattern, final LoggerRepository repository,
+    final ULogger logger) {
+    next = null;
+    handlesExceptions = false;
+
+    List converters = new ArrayList();
+    List fields = new ArrayList();
+    Map converterRegistry = null;
+
+    if (repository instanceof LoggerRepositoryEx) {
+      converterRegistry =
+        (Map) ((LoggerRepositoryEx) repository).getObject(
+          PatternLayout.PATTERN_RULE_REGISTRY);
+    }
+
+    PatternParser.parse(
+      pattern, converters, fields, converterRegistry,
+      PatternParser.getPatternLayoutRules(), logger);
+
+    patternConverters = new LoggingEventPatternConverter[converters.size()];
+    patternFields = new FormattingInfo[converters.size()];
+
+    int i = 0;
+    Iterator converterIter = converters.iterator();
+    Iterator fieldIter = fields.iterator();
+
+    while (converterIter.hasNext()) {
+      Object converter = converterIter.next();
+
+      if (converter instanceof LoggingEventPatternConverter) {
+        patternConverters[i] = (LoggingEventPatternConverter) converter;
+        handlesExceptions |= patternConverters[i].handlesThrowable();
+      } else {
+        patternConverters[i] =
+          new org.apache.log4j.pattern.LiteralPatternConverter("");
+      }
+
+      if (fieldIter.hasNext()) {
+        patternFields[i] = (FormattingInfo) fieldIter.next();
+      } else {
+        patternFields[i] = FormattingInfo.getDefault();
+      }
+
+      i++;
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String convert(final LoggingEvent event) {
+    //
+    //  code should be unreachable.
+    //
+    StringBuffer sbuf = new StringBuffer();
+    format(sbuf, event);
+
+    return sbuf.toString();
+  }
+
+  /**
+     Format event to string buffer.
+     @param sbuf string buffer to receive formatted event, may not be null.
+     @param e event to format, may not be null.
+   */
+  public void format(final StringBuffer sbuf, final LoggingEvent e) {
+    for (int i = 0; i < patternConverters.length; i++) {
+      int startField = sbuf.length();
+      patternConverters[i].format(e, sbuf);
+      patternFields[i].format(startField, sbuf);
+    }
+  }
+
+  /**
+   * Will return false if any of the conversion specifiers in the pattern
+   * handles {@link Exception Exceptions}.
+   * @return true if the pattern formats any information from exceptions.
+   */
+  public boolean ignoresThrowable() {
+    return !handlesExceptions;
+  }
+}

Added: logging/log4j/trunk/src/java/org/apache/log4j/pattern/BridgePatternParser.java
URL: http://svn.apache.org/viewcvs/logging/log4j/trunk/src/java/org/apache/log4j/pattern/BridgePatternParser.java?rev=384131&view=auto
==============================================================================
--- logging/log4j/trunk/src/java/org/apache/log4j/pattern/BridgePatternParser.java (added)
+++ logging/log4j/trunk/src/java/org/apache/log4j/pattern/BridgePatternParser.java Tue Mar  7 22:14:45 2006
@@ -0,0 +1,65 @@
+/*
+ * Copyright 1999,2005 The Apache Software Foundation.
+ *
+ * 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.pattern;
+
+import org.apache.log4j.ULogger;
+import org.apache.log4j.spi.LoggerRepository;
+
+
+/**
+ * The class implements the pre log4j 1.3 org.apache.log4j.helpers.PatternConverter
+ * contract by delegating to the log4j 1.3 pattern implementation.
+ *
+ *
+ * @author Curt Arnold
+ * @since 1.3
+ *
+ */
+public final class BridgePatternParser
+  extends org.apache.log4j.helpers.PatternParser {
+  /**
+   * Logger repository.
+   */
+  private final LoggerRepository repository;
+
+  /**
+   * Internal logger.
+   */
+  private final ULogger logger;
+
+  /**
+   * Create a new instance.
+   * @param conversionPattern pattern, may not be null.
+   * @param repository repository, may be null.
+   * @param logger internal logger, may be null.
+   */
+  public BridgePatternParser(
+    final String conversionPattern, final LoggerRepository repository,
+    final ULogger logger) {
+    super(conversionPattern);
+    this.repository = repository;
+    this.logger = logger;
+  }
+
+  /**
+   * Create new pattern converter.
+   * @return pattern converter.
+   */
+  public org.apache.log4j.helpers.PatternConverter parse() {
+    return new BridgePatternConverter(pattern, repository, logger);
+  }
+}

Added: logging/log4j/trunk/tests/input/pattern/patternLayout15.properties
URL: http://svn.apache.org/viewcvs/logging/log4j/trunk/tests/input/pattern/patternLayout15.properties?rev=384131&view=auto
==============================================================================
--- logging/log4j/trunk/tests/input/pattern/patternLayout15.properties (added)
+++ logging/log4j/trunk/tests/input/pattern/patternLayout15.properties Tue Mar  7 22:14:45 2006
@@ -0,0 +1,12 @@
+log4j.rootCategory=TRACE, testAppender
+log4j.appender.testAppender=org.apache.log4j.FileAppender
+log4j.appender.testAppender.File=       output/temp 
+log4j.appender.testAppender.Append=false
+log4j.appender.testAppender.layout=org.apache.log4j.MyPatternLayout
+log4j.appender.testAppender.layout.ConversionPattern=%5p %-4# - %m%n
+
+#  Prevent internal log4j DEBUG messages from polluting the output.
+log4j.logger.org.apache.log4j.PropertyConfigurator=INFO
+log4j.logger.org.apache.log4j.config.PropertySetter=INFO
+log4j.logger.org.apache.log4j.FileAppender=INFO
+

Added: logging/log4j/trunk/tests/src/java/org/apache/log4j/MyPatternLayout.java
URL: http://svn.apache.org/viewcvs/logging/log4j/trunk/tests/src/java/org/apache/log4j/MyPatternLayout.java?rev=384131&view=auto
==============================================================================
--- logging/log4j/trunk/tests/src/java/org/apache/log4j/MyPatternLayout.java (added)
+++ logging/log4j/trunk/tests/src/java/org/apache/log4j/MyPatternLayout.java Tue Mar  7 22:14:45 2006
@@ -0,0 +1,52 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ * 
+ * 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;
+import org.apache.log4j.helpers.PatternParser;
+
+/**
+
+  Example showing how to extend PatternLayout to recognize additional
+  conversion characters.  
+  
+  <p>In this case MyPatternLayout recognizes %# conversion pattern. It
+  outputs the value of an internal counter which is also incremented
+  at each call.
+
+  <p>See <a href=doc-files/MyPatternLayout.java><b>source</b></a> code
+  for more details.
+
+  @see MyPatternParser
+  @see org.apache.log4j.PatternLayout
+  @author Anders Kristensen 
+*/
+public class MyPatternLayout extends PatternLayout {
+  public
+  MyPatternLayout() {
+    this(DEFAULT_CONVERSION_PATTERN);
+  }
+
+  public
+  MyPatternLayout(String pattern) {
+    super(pattern);
+  }
+    
+  public
+  PatternParser createPatternParser(String pattern) {
+    return new MyPatternParser(
+      pattern == null ? DEFAULT_CONVERSION_PATTERN : pattern);
+  }
+}

Added: logging/log4j/trunk/tests/src/java/org/apache/log4j/MyPatternParser.java
URL: http://svn.apache.org/viewcvs/logging/log4j/trunk/tests/src/java/org/apache/log4j/MyPatternParser.java?rev=384131&view=auto
==============================================================================
--- logging/log4j/trunk/tests/src/java/org/apache/log4j/MyPatternParser.java (added)
+++ logging/log4j/trunk/tests/src/java/org/apache/log4j/MyPatternParser.java Tue Mar  7 22:14:45 2006
@@ -0,0 +1,71 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ * 
+ * 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;
+
+import org.apache.log4j.helpers.FormattingInfo;
+import org.apache.log4j.helpers.PatternConverter;
+import org.apache.log4j.helpers.PatternParser;
+import org.apache.log4j.spi.LoggingEvent;
+
+/**
+  Example showing how to extend PatternParser to recognize additional
+  conversion characters.  The examples shows that minimum and maximum
+  width and alignment settings apply for "extension" conversion
+  characters just as they do for PatternLayout recognized characters.
+  
+  <p>In this case MyPatternParser recognizes %# and outputs the value
+  of an internal counter which is also incremented at each call.
+
+  See <a href=doc-files/MyPatternParser.java><b>source</b></a> code
+   for more details.
+  
+  @see org.apache.log4j.MyPatternLayout
+  @see org.apache.log4j.helpers.PatternParser
+  @see org.apache.log4j.PatternLayout
+
+  @author Anders Kristensen 
+*/
+public class MyPatternParser extends PatternParser {
+
+  int counter = 0;
+
+  public
+  MyPatternParser(String pattern) {
+    super(pattern);
+  }
+    
+  public
+  void finalizeConverter(char c) {
+    if (c == '#') {
+      addConverter(new UserDirPatternConverter(formattingInfo));
+      currentLiteral.setLength(0);
+    } else {
+      super.finalizeConverter(c);
+    }
+  }
+  
+  private class UserDirPatternConverter extends PatternConverter {
+    UserDirPatternConverter(FormattingInfo formattingInfo) {
+      super(formattingInfo);
+    }
+
+    public
+    String convert(LoggingEvent event) {
+      return String.valueOf(++counter);
+    }
+  }  
+}

Modified: logging/log4j/trunk/tests/src/java/org/apache/log4j/PatternLayoutTestCase.java
URL: http://svn.apache.org/viewcvs/logging/log4j/trunk/tests/src/java/org/apache/log4j/PatternLayoutTestCase.java?rev=384131&r1=384130&r2=384131&view=diff
==============================================================================
--- logging/log4j/trunk/tests/src/java/org/apache/log4j/PatternLayoutTestCase.java (original)
+++ logging/log4j/trunk/tests/src/java/org/apache/log4j/PatternLayoutTestCase.java Tue Mar  7 22:14:45 2006
@@ -39,6 +39,8 @@
   static String EXCEPTION1 = "java.lang.Exception: Just testing";
   static String EXCEPTION2 = "\\s*at .*\\(.*:\\d{1,4}\\)";
   static String EXCEPTION3 = "\\s*at .*\\(Native Method\\)";
+  static String EXCEPTION4 = "\\s*at .*\\(.*Compiled Code\\)";
+
   static String PAT0 =
     "\\[main]\\ (DEBUG|INFO|WARN|ERROR|FATAL) .* - Message \\d{1,2}";
   static String PAT1 = Filter.ISO8601_PAT + " " + PAT0;
@@ -62,7 +64,7 @@
     + "apache.log4j.PatternLayoutTestCase.common\\(PatternLayoutTestCase.java:\\d{3}\\): "
     + "Message \\d{1,2}";
   static String PAT14 =
-    "^(DEBUG| INFO| WARN|ERROR|FATAL)\\ \\d{1,2}\\ *- Message \\d{1,2}";
+    "^(TRACE|DEBUG| INFO| WARN|ERROR|FATAL)\\ \\d{1,2}\\ *- Message \\d{1,2}";
   static String PAT_MDC_1 = "";
   Logger root;
   Logger logger;
@@ -322,6 +324,26 @@
     assertTrue(Compare.compare(FILTERED, "witness/pattern/patternLayout.mdc.1"));
   }
 
+    /**
+     * Tests log4j 1.2 style extension of PatternLayout.
+     * Was test14 in log4j 1.2.
+     * @throws Exception
+     */
+    public void test15() throws Exception {
+      PropertyConfigurator.configure("input/pattern/patternLayout15.properties");
+      common();
+      ControlFilter cf1 = new ControlFilter(new String[]{PAT14, EXCEPTION1,
+                                 EXCEPTION2, EXCEPTION3, EXCEPTION4});
+      Transformer.transform(
+        TEMP, FILTERED,
+        new Filter[] {
+          cf1, new LineNumberFilter(), new SunReflectFilter(),
+          new JunitTestRunnerFilter()
+        });
+      assertTrue(Compare.compare(FILTERED, "witness/pattern/patternLayout.15"));
+    }
+
+
   void common() {
     int i = -1;
 
@@ -341,6 +363,7 @@
     root.log(Level.FATAL, "Message " + i);
 
     Exception e = new Exception("Just testing");
+
     logger.debug("Message " + ++i, e);
     logger.info("Message " + ++i, e);
     logger.warn("Message " + ++i, e);
@@ -422,28 +445,5 @@
     root.debug("finished mdc pattern test");
 
     assertTrue(Compare.compare(OUTPUT_FILE, WITNESS_FILE));
-  }
-
-  public static Test XXXsuite() {
-    TestSuite suite = new TestSuite();
-    suite.addTest(new PatternLayoutTest("test1"));
-
-    suite.addTest(new PatternLayoutTest("test2"));
-    suite.addTest(new PatternLayoutTest("test3"));
-    suite.addTest(new PatternLayoutTest("test4"));
-    suite.addTest(new PatternLayoutTest("test5"));
-    suite.addTest(new PatternLayoutTest("test6"));
-    suite.addTest(new PatternLayoutTest("test7"));
-    suite.addTest(new PatternLayoutTest("test8"));
-    suite.addTest(new PatternLayoutTest("test9"));
-    suite.addTest(new PatternLayoutTest("test10"));
-    suite.addTest(new PatternLayoutTest("test11"));
-    suite.addTest(new PatternLayoutTest("test12"));
-    suite.addTest(new PatternLayoutTest("test13"));
-    suite.addTest(new PatternLayoutTest("test14"));
-    suite.addTest(new PatternLayoutTest("testMDC1"));
-    suite.addTest(new PatternLayoutTest("testMDC2"));
-    
-    return suite;
   }
 }

Added: logging/log4j/trunk/tests/witness/pattern/patternLayout.15
URL: http://svn.apache.org/viewcvs/logging/log4j/trunk/tests/witness/pattern/patternLayout.15?rev=384131&view=auto
==============================================================================
--- logging/log4j/trunk/tests/witness/pattern/patternLayout.15 (added)
+++ logging/log4j/trunk/tests/witness/pattern/patternLayout.15 Tue Mar  7 22:14:45 2006
@@ -0,0 +1,75 @@
+DEBUG 1    - Message 0
+DEBUG 2    - Message 0
+ INFO 3    - Message 1
+ INFO 4    - Message 1
+ WARN 5    - Message 2
+ WARN 6    - Message 2
+ERROR 7    - Message 3
+ERROR 8    - Message 3
+FATAL 9    - Message 4
+FATAL 10   - Message 4
+DEBUG 11   - Message 5
+java.lang.Exception: Just testing
+	at org.apache.log4j.PatternLayoutTestCase.common(X)
+	at org.apache.log4j.PatternLayoutTestCase.test15(X)
+	at java.lang.reflect.Method.invoke(X)
+	at junit.framework.TestCase.runTest(X)
+	at junit.framework.TestCase.runBare(X)
+	at junit.framework.TestResult$1.protect(X)
+	at junit.framework.TestResult.runProtected(X)
+	at junit.framework.TestResult.run(X)
+	at junit.framework.TestCase.run(X)
+	at junit.framework.TestSuite.runTest(X)
+	at junit.framework.TestSuite.run(X)
+ INFO 12   - Message 6
+java.lang.Exception: Just testing
+	at org.apache.log4j.PatternLayoutTestCase.common(X)
+	at org.apache.log4j.PatternLayoutTestCase.test15(X)
+	at java.lang.reflect.Method.invoke(X)
+	at junit.framework.TestCase.runTest(X)
+	at junit.framework.TestCase.runBare(X)
+	at junit.framework.TestResult$1.protect(X)
+	at junit.framework.TestResult.runProtected(X)
+	at junit.framework.TestResult.run(X)
+	at junit.framework.TestCase.run(X)
+	at junit.framework.TestSuite.runTest(X)
+	at junit.framework.TestSuite.run(X)
+ WARN 13   - Message 7
+java.lang.Exception: Just testing
+	at org.apache.log4j.PatternLayoutTestCase.common(X)
+	at org.apache.log4j.PatternLayoutTestCase.test15(X)
+	at java.lang.reflect.Method.invoke(X)
+	at junit.framework.TestCase.runTest(X)
+	at junit.framework.TestCase.runBare(X)
+	at junit.framework.TestResult$1.protect(X)
+	at junit.framework.TestResult.runProtected(X)
+	at junit.framework.TestResult.run(X)
+	at junit.framework.TestCase.run(X)
+	at junit.framework.TestSuite.runTest(X)
+	at junit.framework.TestSuite.run(X)
+ERROR 14   - Message 8
+java.lang.Exception: Just testing
+	at org.apache.log4j.PatternLayoutTestCase.common(X)
+	at org.apache.log4j.PatternLayoutTestCase.test15(X)
+	at java.lang.reflect.Method.invoke(X)
+	at junit.framework.TestCase.runTest(X)
+	at junit.framework.TestCase.runBare(X)
+	at junit.framework.TestResult$1.protect(X)
+	at junit.framework.TestResult.runProtected(X)
+	at junit.framework.TestResult.run(X)
+	at junit.framework.TestCase.run(X)
+	at junit.framework.TestSuite.runTest(X)
+	at junit.framework.TestSuite.run(X)
+FATAL 15   - Message 9
+java.lang.Exception: Just testing
+	at org.apache.log4j.PatternLayoutTestCase.common(X)
+	at org.apache.log4j.PatternLayoutTestCase.test15(X)
+	at java.lang.reflect.Method.invoke(X)
+	at junit.framework.TestCase.runTest(X)
+	at junit.framework.TestCase.runBare(X)
+	at junit.framework.TestResult$1.protect(X)
+	at junit.framework.TestResult.runProtected(X)
+	at junit.framework.TestResult.run(X)
+	at junit.framework.TestCase.run(X)
+	at junit.framework.TestSuite.runTest(X)
+	at junit.framework.TestSuite.run(X)



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