carnold 2005/03/07 15:50:27 Modified: src/java/org/apache/log4j/pattern ClassNamePatternConverter.java LoggerPatternConverter.java NamedPatternConverter.java PatternParser.java tests/src/java/org/apache/log4j PatternLayoutTest.java tests/src/java/org/apache/log4j/pattern PatternParserTest.java tests/witness/pattern patternLayout.14 Added: src/java/org/apache/log4j/pattern NameAbbreviator.java tests/input/pattern patternLayout14.properties tests/src/java/org/apache/log4j/pattern NameAbbreviatorTest.java Log: Bug 33888: Enhanced abbreviation syntax for logger and class name Revision Changes Path 1.10 +19 -17 logging-log4j/src/java/org/apache/log4j/pattern/ClassNamePatternConverter.java Index: ClassNamePatternConverter.java =================================================================== RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/pattern/ClassNamePatternConverter.java,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- ClassNamePatternConverter.java 20 Nov 2004 11:27:19 -0000 1.9 +++ ClassNamePatternConverter.java 7 Mar 2005 23:50:27 -0000 1.10 @@ -1,12 +1,12 @@ /* - * Copyright 1999,2004 The Apache Software Foundation. - * + * 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. @@ -19,35 +19,37 @@ import org.apache.log4j.spi.LoggingEvent; import org.apache.log4j.spi.location.LocationInfo; + /** - * Most of the work is done in the parent class [EMAIL PROTECTED] + * Most of the work is done in the parent class [EMAIL PROTECTED] * org.apache.log4j.pattern.NamedPatternConverter NamedPatternConverter}. * This class is only responsible of returning the full name name of the caller - * class. - * + * class. + * * @author Ceki Gülcü */ public class ClassNamePatternConverter extends NamedPatternConverter { - static private final String NAME = "Class Name"; - static private final String STYLE_CLASS = NAME.toLowerCase(); + private static final String NAME = "Class Name"; + private static final String STYLE_CLASS = NAME.toLowerCase(); public ClassNamePatternConverter() { super(); } - - String getFullyQualifiedName(LoggingEvent event) { + + protected String getFullyQualifiedName(LoggingEvent event) { LocationInfo li = event.getLocationInformation(); - if(li == null) { + + if (li == null) { return LocationInfo.NA; } else { - return li.getClassName(); + return li.getClassName(); } - } - + } + public String getName() { - return NAME; + return NAME; } - + public String getStyleClass(LoggingEvent e) { return STYLE_CLASS; } 1.6 +13 -14 logging-log4j/src/java/org/apache/log4j/pattern/LoggerPatternConverter.java Index: LoggerPatternConverter.java =================================================================== RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/pattern/LoggerPatternConverter.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- LoggerPatternConverter.java 16 Sep 2004 19:18:58 -0000 1.5 +++ LoggerPatternConverter.java 7 Mar 2005 23:50:27 -0000 1.6 @@ -1,12 +1,12 @@ /* - * Copyright 1999,2004 The Apache Software Foundation. - * + * 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. @@ -18,30 +18,29 @@ import org.apache.log4j.spi.LoggingEvent; + /** - * - * + * + * * @author Ceki Gülcü */ public class LoggerPatternConverter extends NamedPatternConverter { // We assume that each PatternConveter instance is unique within a layout, // which is unique within an appender. We further assume that callas to the // appender method are serialized (per appender). - public LoggerPatternConverter() { super(); } - String getFullyQualifiedName(LoggingEvent event) { - return event.getLoggerName(); - } - + protected String getFullyQualifiedName(LoggingEvent event) { + return event.getLoggerName(); + } + public String getName() { - return "Logger"; + return "Logger"; } - + public String getStyleClass(LoggingEvent e) { return "logger"; } - } 1.7 +42 -66 logging-log4j/src/java/org/apache/log4j/pattern/NamedPatternConverter.java Index: NamedPatternConverter.java =================================================================== RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/pattern/NamedPatternConverter.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- NamedPatternConverter.java 6 Jan 2005 19:27:03 -0000 1.6 +++ NamedPatternConverter.java 7 Mar 2005 23:50:27 -0000 1.7 @@ -1,12 +1,12 @@ /* - * Copyright 1999,2004 The Apache Software Foundation. - * + * 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. @@ -16,87 +16,63 @@ package org.apache.log4j.pattern; -import java.util.List; - import org.apache.log4j.spi.LoggingEvent; +import java.util.List; + /** - * + * * Base class for other pattern converters which can return only parts of their name. - * + * * @author Ceki Gülcü + * @author Curt Arnold */ -abstract class NamedPatternConverter extends PatternConverter { - +public abstract class NamedPatternConverter extends PatternConverter { // We assume that each PatternConveter instance is unique within a layout, // which is unique within an appender. We further assume that callas to the // appender method are serialized (per appender). - StringBuffer buf; - int precision; + private final StringBuffer buf = new StringBuffer(32); + private NameAbbreviator abbreviator = + NameAbbreviator.getDefaultAbbreviator(); - public NamedPatternConverter() { - super(); - this.buf = new StringBuffer(32); + protected NamedPatternConverter() { } - abstract String getFullyQualifiedName(LoggingEvent event); - - public void setOptions(List optionList) { - if(optionList == null || optionList.size() == 0) { - return; - } - - String option = (String) optionList.get(0); - - /** - The option is expected to be in decimal and positive. In case of - error, zero is returned. */ - int r = 0; - - if (option != null) { - try { - precision = Integer.parseInt(option); - //System.out.println("Precision is "+precision); - if (precision <= 0) { - getLogger().error( - "Precision option (" + option + ") isn't a positive integer."); - precision = 0; - } - } catch (NumberFormatException e) { - getLogger().error( - "Category option \"" + option + "\" not a decimal integer.", e); - } + /** + * Gets fully qualified name from event. + * @param event event, will not be null. + * @return name, must not be null. + */ + protected abstract String getFullyQualifiedName(final LoggingEvent event); + + /** + * Sets converter options. + * + * NamedPatternConverter interprets the first parameter as an + * abbreviation specification. + * + * @param optionList option list. + */ + public void setOptions(final List optionList) { + if ((optionList != null) && (optionList.size() > 0)) { + String option = (String) optionList.get(0); + abbreviator = NameAbbreviator.getAbbreviator(option); } } - public StringBuffer convert(LoggingEvent event) { + /** + * Convert event. + * + * @param event event, may not be null. + * @return string buffer used in conversion. + */ + public StringBuffer convert(final LoggingEvent event) { buf.setLength(0); String n = getFullyQualifiedName(event); - if (precision <= 0) { - buf.append(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) { - // not enough dot characters. The whole string should be returned - return buf.append(n); - } - } - - // The end variable should point to the left-most dot character to - // the right of which all character should be returned. - buf.append(n.substring(end + 1, len)); - } + abbreviator.abbreviate(buf, n); + return buf; } } 1.23 +162 -128 logging-log4j/src/java/org/apache/log4j/pattern/PatternParser.java Index: PatternParser.java =================================================================== RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/pattern/PatternParser.java,v retrieving revision 1.22 retrieving revision 1.23 diff -u -r1.22 -r1.23 --- PatternParser.java 8 Jan 2005 14:05:28 -0000 1.22 +++ PatternParser.java 7 Mar 2005 23:50:27 -0000 1.23 @@ -1,12 +1,12 @@ /* - * Copyright 1999,2004 The Apache Software Foundation. - * + * 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. @@ -20,10 +20,10 @@ import org.apache.log4j.spi.ComponentBase; import org.apache.log4j.spi.LoggerRepository; +import java.util.ArrayList; import java.util.HashMap; -import java.util.Map; import java.util.List; -import java.util.ArrayList; +import java.util.Map; // Contributors: Nelson Minar <([EMAIL PROTECTED]> @@ -31,19 +31,20 @@ // Reinhard Deschler <[EMAIL PROTECTED]> /** - * Most of the work of the [EMAIL PROTECTED] org.apache.log4j.PatternLayout} class - * is delegated to the PatternParser class. - * <p>It is this class that parses conversion patterns and creates + * Most of the work of the [EMAIL PROTECTED] 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 [EMAIL PROTECTED] OptionConverter OptionConverters}. - * + * * @author James P. Cakalic * @author Ceki Gülcü * @author Anders Kristensen * @author Paul Smith + * @author Curt Arnold * * @since 0.8.2 */ -public class PatternParser extends ComponentBase { +public final class PatternParser extends ComponentBase { private static final char ESCAPE_CHAR = '%'; private static final int LITERAL_STATE = 0; private static final int CONVERTER_STATE = 1; @@ -51,78 +52,81 @@ private static final int DOT_STATE = 3; private static final int MIN_STATE = 4; private static final int MAX_STATE = 5; - - static Map globalRulesRegistry; + private static Map globalRulesRegistry; static { // We set the global rules in the static initializer of PatternParser class globalRulesRegistry = new HashMap(17); - globalRulesRegistry.put("c", LoggerPatternConverter.class.getName()); - globalRulesRegistry.put("logger", LoggerPatternConverter.class.getName()); - - globalRulesRegistry.put("C", ClassNamePatternConverter.class.getName()); - globalRulesRegistry.put("class", ClassNamePatternConverter.class.getName()); - - globalRulesRegistry.put("d", DatePatternConverter.class.getName()); - globalRulesRegistry.put("date", DatePatternConverter.class.getName()); - - globalRulesRegistry.put("F", FileLocationPatternConverter.class.getName()); - globalRulesRegistry.put("file", FileLocationPatternConverter.class.getName()); - - globalRulesRegistry.put("l", FullLocationPatternConverter.class.getName()); + globalRulesRegistry.put("c", LoggerPatternConverter.class); + globalRulesRegistry.put("logger", LoggerPatternConverter.class); + + globalRulesRegistry.put("C", ClassNamePatternConverter.class); + globalRulesRegistry.put("class", ClassNamePatternConverter.class); + + globalRulesRegistry.put("d", DatePatternConverter.class); + globalRulesRegistry.put("date", DatePatternConverter.class); + + globalRulesRegistry.put("F", FileLocationPatternConverter.class); + globalRulesRegistry.put("file", FileLocationPatternConverter.class); + + globalRulesRegistry.put("l", FullLocationPatternConverter.class); + + globalRulesRegistry.put("L", LineLocationPatternConverter.class); + globalRulesRegistry.put("line", LineLocationPatternConverter.class); + + globalRulesRegistry.put("m", MessagePatternConverter.class); + globalRulesRegistry.put("message", MessagePatternConverter.class); - globalRulesRegistry.put("L", LineLocationPatternConverter.class.getName()); - globalRulesRegistry.put("line", LineLocationPatternConverter.class.getName()); + globalRulesRegistry.put("n", LineSeparatorPatternConverter.class); - globalRulesRegistry.put("m", MessagePatternConverter.class.getName()); - globalRulesRegistry.put("message", MessagePatternConverter.class.getName()); + globalRulesRegistry.put("M", MethodLocationPatternConverter.class); + globalRulesRegistry.put("method", MethodLocationPatternConverter.class); - globalRulesRegistry.put("n", LineSeparatorPatternConverter.class.getName()); + globalRulesRegistry.put("p", LevelPatternConverter.class); + globalRulesRegistry.put("level", LevelPatternConverter.class); + globalRulesRegistry.put("r", RelativeTimePatternConverter.class); + globalRulesRegistry.put("relative", RelativeTimePatternConverter.class); + + globalRulesRegistry.put("t", ThreadPatternConverter.class); + globalRulesRegistry.put("thread", ThreadPatternConverter.class); + + globalRulesRegistry.put("x", NDCPatternConverter.class); + globalRulesRegistry.put("ndc", NDCPatternConverter.class); + + globalRulesRegistry.put("X", PropertiesPatternConverter.class); + globalRulesRegistry.put("properties", PropertiesPatternConverter.class); + + globalRulesRegistry.put("sn", SequenceNumberPatternConverter.class); globalRulesRegistry.put( - "M", MethodLocationPatternConverter.class.getName()); + "sequenceNumber", SequenceNumberPatternConverter.class); + globalRulesRegistry.put( - "method", MethodLocationPatternConverter.class.getName()); + "throwable", ThrowableInformationPatternConverter.class); + } + + private int state; + private StringBuffer currentLiteral = new StringBuffer(32); + private int patternLength; + private int i; + private PatternConverter head; + private PatternConverter tail; + private FormattingInfo formattingInfo = new FormattingInfo(); + private String pattern; - globalRulesRegistry.put("p", LevelPatternConverter.class.getName()); - globalRulesRegistry.put("level", LevelPatternConverter.class.getName()); - - globalRulesRegistry.put("r", RelativeTimePatternConverter.class.getName()); - globalRulesRegistry.put("relative", RelativeTimePatternConverter.class.getName()); - - globalRulesRegistry.put("t", ThreadPatternConverter.class.getName()); - globalRulesRegistry.put("thread", ThreadPatternConverter.class.getName()); - - globalRulesRegistry.put("x", NDCPatternConverter.class.getName()); - globalRulesRegistry.put("ndc", NDCPatternConverter.class.getName()); - - globalRulesRegistry.put("X", PropertiesPatternConverter.class.getName()); - globalRulesRegistry.put("properties", PropertiesPatternConverter.class.getName()); - - globalRulesRegistry.put("sn", SequenceNumberPatternConverter.class.getName()); - globalRulesRegistry.put("sequenceNumber", SequenceNumberPatternConverter.class.getName()); - - globalRulesRegistry.put("throwable", ThrowableInformationPatternConverter.class.getName()); - - } - - 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; - /** * Additional rules for this particular instance. * key: the conversion word (as String) - * value: the pattern converter class (as String) + * value: the pattern converter class (as String) */ - Map converterRegistry; + private Map converterRegistry; + + public PatternParser( + final String pattern, final LoggerRepository repository) { + if (pattern == null) { + throw new NullPointerException("pattern"); + } - public PatternParser(String pattern, LoggerRepository repository) { this.pattern = pattern; this.repository = repository; patternLength = pattern.length(); @@ -147,25 +151,24 @@ * start of a unicode identifier, the value null is returned. * */ - protected String extractConverter(char lastChar) { - + private String extractConverter(char lastChar) { // When this method is called, lastChar points to the first character of the // conersion word. For example: // For "%hello" lastChar = 'h' // For "%-5hello" lastChar = 'h' - - //System.out.println("lastchar is "+lastChar); - - if(!Character.isUnicodeIdentifierStart(lastChar)) { + //System.out.println("lastchar is "+lastChar); + if (!Character.isUnicodeIdentifierStart(lastChar)) { return null; - } - + } + StringBuffer convBuf = new StringBuffer(16); - convBuf.append(lastChar); - - while ((i < patternLength) - && Character.isUnicodeIdentifierPart(pattern.charAt(i))) { + convBuf.append(lastChar); + + while ( + (i < patternLength) + && Character.isUnicodeIdentifierPart(pattern.charAt(i))) { convBuf.append(pattern.charAt(i)); + //System.out.println("conv buffer is now ["+convBuf+"]."); i++; } @@ -176,15 +179,17 @@ /** * Returns the option, null if not in the expected format. */ - protected List extractOptions() { + private List extractOptions() { ArrayList options = null; + while ((i < patternLength) && (pattern.charAt(i) == '{')) { int end = pattern.indexOf('}', i); if (end > i) { if (options == null) { - options = new ArrayList(); + options = new ArrayList(); } + String r = pattern.substring(i + 1, end); options.add(r); i = end + 1; @@ -319,68 +324,88 @@ return head; } - String findConverterClass(String converterId) { - if(converterId == null) { + /** + * Creates a new pattern converter. + * @param converterId converter identifier. + * @param formattingInfo formatting info. + * @param options options. + * @return pattern converter, may be null. + */ + private PatternConverter createConverter( + final String converterId, final FormattingInfo formattingInfo, + final List options) { + PatternConverter converter = null; + + if (converterId == null) { getLogger().warn("converterId is null"); - } - - if (converterRegistry != null) { - String r = (String) converterRegistry.get(converterId); + } else { + if (converterRegistry != null) { + String r = (String) converterRegistry.get(converterId); + + if (r != null) { + converter = + (PatternConverter) OptionConverter.instantiateByClassName( + r, PatternConverter.class, null); + } + } - if (r != null) { - return r; + Class converterClass = (Class) globalRulesRegistry.get(converterId); + + if (converterClass != null) { + try { + converter = (PatternConverter) converterClass.newInstance(); + } catch (Exception ex) { + getLogger().error("Error creating converter for " + converterId, ex); + } } } - - String r = (String) globalRulesRegistry.get(converterId); - if (r != null) { - return r; - } - return null; + if (converter != null) { + converter.setFormattingInfo(formattingInfo); + converter.setOptions(options); + } + + return converter; } /** * When finalizeConverter is called 'c' is the current conversion caracter * and i points to the character following 'c'. */ - protected void finalizeConverter(char c) { - PatternConverter pc = null; - + private void finalizeConverter(char c) { String converterId = extractConverter(c); - //System.out.println("converter ID[" + converterId + "]"); - //System.out.println("c is [" + c + "]"); - String className = (String) findConverterClass(converterId); - - //System.out.println("converter class [" + className + "]"); - List options = extractOptions(); - //System.out.println("Option is [" + option + "]"); - if (className != null) { - pc = (PatternConverter) OptionConverter.instantiateByClassName( - className, PatternConverter.class, null); - - // setting the logger repository is an important configuration step. - pc.setLoggerRepository(this.repository); - - // formattingInfo variable is an instance variable, occasionally reset - // and used over and over again - pc.setFormattingInfo(formattingInfo); - pc.setOptions(options); - currentLiteral.setLength(0); - } else { - getLogger().error( - "Unexpected char [" + c + "] at position " + i - + " in conversion patterrn."); - pc = new LiteralPatternConverter(currentLiteral.toString()); - currentLiteral.setLength(0); + PatternConverter pc = + createConverter(converterId, formattingInfo, options); + + if (pc == null) { + StringBuffer msg; + + if ((converterId == null) || (converterId.length() == 0)) { + msg = + new StringBuffer("Empty conversion specifier starting at position "); + } else { + msg = new StringBuffer("Unrecognized conversion specifier ["); + msg.append(converterId); + msg.append("] starting at position "); + } + + msg.append(Integer.toString(i)); + msg.append(" in conversion pattern."); + getLogger().error(msg.toString()); + pc = new LiteralPatternConverter(currentLiteral.toString()); } + + // setting the logger repository is an important configuration step. + pc.setLoggerRepository(this.repository); + + currentLiteral.setLength(0); addConverter(pc); } - protected void addConverter(PatternConverter pc) { + private void addConverter(final PatternConverter pc) { currentLiteral.setLength(0); // Add the pattern converter to the list. @@ -395,16 +420,25 @@ /** * Returns the converter registry for this PatternParser instance. + * @return map of custom pattern converters, may be null. */ public Map getConverterRegistry() { - return converterRegistry; + if (converterRegistry == null) { + return null; + } + + return new HashMap(converterRegistry); } /** * Set the converter registry for this PatternParser instance. + * @param converterRegistry map of format specifiers to class names, may be null. */ - public void setConverterRegistry(Map converterRegistry) { - this.converterRegistry = converterRegistry; + public void setConverterRegistry(final Map converterRegistry) { + if (converterRegistry == null) { + this.converterRegistry = null; + } else { + this.converterRegistry = new HashMap(converterRegistry); + } } - } 1.1 logging-log4j/src/java/org/apache/log4j/pattern/NameAbbreviator.java Index: NameAbbreviator.java =================================================================== /* * 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 java.util.ArrayList; import java.util.List; /** * NameAbbreviator generates abbreviated logger and class names. * * @author Curt Arnold * @since 1.3 */ public abstract class NameAbbreviator { /** * Default (no abbreviation) abbreviator. */ private static final NameAbbreviator defaultAbbreviator = new NOPAbbreviator(); /** * Gets an abbreviator. * * * @param pattern abbreviation pattern. * @return abbreviator, will not be null. */ public static NameAbbreviator getAbbreviator(final String pattern) { if (pattern.length() > 0) { // if pattern is just spaces and numbers then // use MaxElementAbbreviator String trimmed = pattern.trim(); if (trimmed.length() == 0) { return defaultAbbreviator; } int i = 0; for ( ; (i < trimmed.length()) && (trimmed.charAt(i) >= '0') && (trimmed.charAt(i) <= '9'); i++) ; // // if all blanks and digits // if (i == trimmed.length()) { return new MaxElementAbbreviator(Integer.parseInt(trimmed)); } ArrayList fragments = new ArrayList(5); char ellipsis; int charCount; int pos = 0; while ((pos < trimmed.length()) && (pos >= 0)) { int ellipsisPos = pos; if (trimmed.charAt(pos) == '*') { charCount = Integer.MAX_VALUE; ellipsisPos++; } else { if ((trimmed.charAt(pos) >= '0') && (trimmed.charAt(pos) <= '9')) { charCount = trimmed.charAt(pos) - '0'; ellipsisPos++; } else { charCount = 0; } } ellipsis = '\0'; if (ellipsisPos < trimmed.length()) { ellipsis = trimmed.charAt(ellipsisPos); if (ellipsis == '.') { ellipsis = '\0'; } } fragments.add(new PatternAbbreviatorFragment(charCount, ellipsis)); pos = trimmed.indexOf(".", pos); if (pos == -1) { break; } pos++; } return new PatternAbbreviator(fragments); } // // no matching abbreviation, return defaultAbbreviator // return defaultAbbreviator; } /** * Gets default abbreviator. * * @return default abbreviator. */ public static NameAbbreviator getDefaultAbbreviator() { return defaultAbbreviator; } /** * Appends abbreviated name to StringBuffer. * * * @param buf buffer, may not be null. * @param name name, may not be null. * */ public abstract void abbreviate(final StringBuffer buf, String name); /** * Abbreviator that simply appends full name to buffer. */ private static class NOPAbbreviator extends NameAbbreviator { public NOPAbbreviator() { } public void abbreviate(final StringBuffer buf, String name) { buf.append(name); } } /** * Abbreviator that drops starting path elements. */ private static class MaxElementAbbreviator extends NameAbbreviator { private final int count; /** * Create new instance. * @param count maximum number of path elements to output. */ public MaxElementAbbreviator(final int count) { this.count = count; } /** * Abbreviate name. * @param buf buffer to append abbreviation. * @param name name to abbreviate. */ public void abbreviate(final StringBuffer buf, String name) { int len = name.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 = count; i > 0; i--) { end = name.lastIndexOf('.', end - 1); if (end == -1) { // not enough dot characters. The whole string should be returned buf.append(name); return; } } // The end variable should point to the left-most dot character to // the right of which all character should be returned. buf.append(name.substring(end + 1, len)); } } /** * Fragment of an pattern abbreviator. * */ private static class PatternAbbreviatorFragment { /** * Count of initial characters of element to output. */ private final int charCount; /** * Character used to represent dropped characters. * '\0' indicates no representation of dropped characters. */ private final char ellipsis; /** * Creates a PatternAbbreviatorFragment. * @param charCount number of initial characters to preserve. * @param ellipsis character to represent elimination of characters, * '\0' if no ellipsis is desired. */ public PatternAbbreviatorFragment( final int charCount, final char ellipsis) { this.charCount = charCount; this.ellipsis = ellipsis; } /** * Abbreviate element of name. * @param buf buffer to receive element. * @param name name. * @param startPos starting index of name element. * @return starting index of next element. */ public int abbreviate( final StringBuffer buf, final String name, final int startPos) { int nextDot = name.indexOf(".", startPos); if (nextDot != -1) { if ((nextDot - startPos) > charCount) { if (charCount > 0) { buf.append(name.substring(startPos, startPos + charCount)); } if (ellipsis != '\0') { buf.append(ellipsis); } buf.append('.'); } else { buf.append(name.substring(startPos, nextDot + 1)); } return nextDot + 1; } buf.append(name.substring(startPos)); return name.length(); } } /** * Pattern abbreviator. * * */ private static class PatternAbbreviator extends NameAbbreviator { /** * Element abbreviation patterns. */ private final PatternAbbreviatorFragment[] fragments; /** * Create PatternAbbreviator. * * @param fragments element abbreviation patterns. */ public PatternAbbreviator(List fragments) { if (fragments.size() == 0) { throw new IllegalArgumentException( "fragments must have at least one element"); } this.fragments = new PatternAbbreviatorFragment[fragments.size()]; fragments.toArray(this.fragments); } /** * Abbreviate name. * @param buf buffer that abbreviated name is appended. * @param name name. */ public void abbreviate(final StringBuffer buf, final String name) { // // all non-terminal patterns are executed once // int pos = 0; for (int i = 0; (i < (fragments.length - 1)) && (pos < name.length()); i++) { pos = fragments[i].abbreviate(buf, name, pos); } // // last pattern in executed repeatedly // PatternAbbreviatorFragment terminalFragment = fragments[fragments.length - 1]; while (pos < name.length()) { pos = terminalFragment.abbreviate(buf, name, pos); } } } } 1.4 +4 -4 logging-log4j/tests/input/pattern/patternLayout14.properties 1.9 +19 -0 logging-log4j/tests/src/java/org/apache/log4j/PatternLayoutTest.java Index: PatternLayoutTest.java =================================================================== RCS file: /home/cvs/logging-log4j/tests/src/java/org/apache/log4j/PatternLayoutTest.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- PatternLayoutTest.java 28 Dec 2004 23:08:12 -0000 1.8 +++ PatternLayoutTest.java 7 Mar 2005 23:50:27 -0000 1.9 @@ -287,6 +287,25 @@ assertTrue(Compare.compare(FILTERED, "witness/pattern/patternLayout.13")); } + /** + * Test of class abbreviation. + * + * @throws Exception + */ + public void test14() throws Exception { + PropertyConfigurator.configure("input/pattern/patternLayout14.properties"); + common(); + + Transformer.transform( + TEMP, FILTERED, + new Filter[] { + new LineNumberFilter(), new SunReflectFilter(), + new JunitTestRunnerFilter() + }); + assertTrue(Compare.compare(FILTERED, "witness/pattern/patternLayout.14")); + } + + public void testMDC1() throws Exception { PropertyConfigurator.configure("input/pattern/patternLayout.mdc.1.properties"); MDC.put("key1", "va11"); 1.9 +8 -6 logging-log4j/tests/src/java/org/apache/log4j/pattern/PatternParserTest.java Index: PatternParserTest.java =================================================================== RCS file: /home/cvs/logging-log4j/tests/src/java/org/apache/log4j/pattern/PatternParserTest.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- PatternParserTest.java 4 Jan 2005 19:42:10 -0000 1.8 +++ PatternParserTest.java 7 Mar 2005 23:50:27 -0000 1.9 @@ -17,6 +17,8 @@ package org.apache.log4j.pattern; import junit.framework.TestCase; +import junit.framework.Test; +import junit.framework.TestSuite; import org.apache.log4j.Layout; import org.apache.log4j.Level; @@ -166,10 +168,10 @@ } -// public static Test suite() { -// TestSuite suite = new TestSuite(); -// suite.addTest(new PatternParserTest("testBasic2")); -// -// return suite; -// } + public static Test suite() { + TestSuite suite = new TestSuite(); + suite.addTestSuite(PatternParserTest.class); + suite.addTestSuite(NameAbbreviatorTest.class); + return suite; + } } 1.1 logging-log4j/tests/src/java/org/apache/log4j/pattern/NameAbbreviatorTest.java Index: NameAbbreviatorTest.java =================================================================== /* * 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 junit.framework.TestCase; /** * Tests for NameAbbrevator. * * @author Curt Arnold * @since 1.3 * */ public class NameAbbreviatorTest extends TestCase { /** * Create a new instance. * * @param name test name */ public NameAbbreviatorTest(final String name) { super(name); } /** * Check that getDefaultAbbreviator does not return null. * */ public void testGetDefault() { NameAbbreviator abbrev = NameAbbreviator.getDefaultAbbreviator(); assertNotNull(abbrev); } /** * Check that "0" drops all name content. * */ public void testZero() { NameAbbreviator abbrev = NameAbbreviator.getAbbreviator("0"); StringBuffer buf = new StringBuffer("DEBUG - "); abbrev.abbreviate(buf, "org.example.foo.bar"); assertEquals("DEBUG - ", buf.toString()); } /** * Check that getAbbreviator(" ") returns default abbreviator. * */ public void testBlank() { NameAbbreviator abbrev = NameAbbreviator.getAbbreviator(" "); NameAbbreviator defaultAbbrev = NameAbbreviator.getDefaultAbbreviator(); assertTrue(abbrev == defaultAbbrev); } /** * Check that getAbbreviator("1").abbreviate() drops all but the final name element. * */ public void testOne() { NameAbbreviator abbrev = NameAbbreviator.getAbbreviator("1"); StringBuffer buf = new StringBuffer("DEBUG - "); abbrev.abbreviate(buf, "org.example.foo.bar"); assertEquals("DEBUG - bar", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, "bar"); assertEquals("DEBUG - bar", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, ""); assertEquals("DEBUG - ", buf.toString()); } /** * Check that blanks are trimmed in evaluating abbreviation pattern. */ public void testBlankOne() { NameAbbreviator abbrev = NameAbbreviator.getAbbreviator(" 1 "); StringBuffer buf = new StringBuffer("DEBUG - "); abbrev.abbreviate(buf, "org.example.foo.bar"); assertEquals("DEBUG - bar", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, "bar"); assertEquals("DEBUG - bar", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, ""); assertEquals("DEBUG - ", buf.toString()); } /** * Check that getAbbreviator("2").abbreviate drops all but the last two elements. * */ public void testTwo() { NameAbbreviator abbrev = NameAbbreviator.getAbbreviator("2"); StringBuffer buf = new StringBuffer("DEBUG - "); abbrev.abbreviate(buf, "org.example.foo.bar"); assertEquals("DEBUG - foo.bar", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, "foo.bar"); assertEquals("DEBUG - foo.bar", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, "bar"); assertEquals("DEBUG - bar", buf.toString()); } /** * Check that getAbbreviator("1.").abbreviate abbreviates non-final elements * to one character. * */ public void testOneDot() { NameAbbreviator abbrev = NameAbbreviator.getAbbreviator("1."); StringBuffer buf = new StringBuffer("DEBUG - "); abbrev.abbreviate(buf, "org.example.foo.bar"); assertEquals("DEBUG - o.e.f.bar", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, "org.example.foo."); assertEquals("DEBUG - o.e.f.", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, "foo.bar"); assertEquals("DEBUG - f.bar", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, "bar"); assertEquals("DEBUG - bar", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, ""); assertEquals("DEBUG - ", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, "."); assertEquals("DEBUG - .", buf.toString()); } /** * Check that getAbbreviator("1~.").abbreviate abbreviates non-final elements * to one character and a tilde. * */ public void testOneTildeDot() { NameAbbreviator abbrev = NameAbbreviator.getAbbreviator("1~."); StringBuffer buf = new StringBuffer("DEBUG - "); abbrev.abbreviate(buf, "org.example.foo.bar"); assertEquals("DEBUG - o~.e~.f~.bar", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, "org.example.foo."); assertEquals("DEBUG - o~.e~.f~.", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, "foo.bar"); assertEquals("DEBUG - f~.bar", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, "bar"); assertEquals("DEBUG - bar", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, ""); assertEquals("DEBUG - ", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, "."); assertEquals("DEBUG - .", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, "o.e.f.bar"); assertEquals("DEBUG - o.e.f.bar", buf.toString()); } /** * Check that getAbbreviator("1.*.2").abbreviate drops all but the first * character from the first element, uses all of the second element and * drops all but the first two characters of the rest of the non-final elements. * */ public void testMulti() { NameAbbreviator abbrev = NameAbbreviator.getAbbreviator("1.*.2"); StringBuffer buf = new StringBuffer("DEBUG - "); abbrev.abbreviate(buf, "org.example.foo.bar"); assertEquals("DEBUG - o.example.fo.bar", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, "org.example.foo."); assertEquals("DEBUG - o.example.fo.", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, "foo.bar"); assertEquals("DEBUG - f.bar", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, "bar"); assertEquals("DEBUG - bar", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, ""); assertEquals("DEBUG - ", buf.toString()); buf.setLength(0); buf.append("DEBUG - "); abbrev.abbreviate(buf, "."); assertEquals("DEBUG - .", buf.toString()); } } 1.2 +15 -15 logging-log4j/tests/witness/pattern/patternLayout.14 Index: patternLayout.14 =================================================================== RCS file: /home/cvs/logging-log4j/tests/witness/pattern/patternLayout.14,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- patternLayout.14 20 Nov 2004 12:58:23 -0000 1.1 +++ patternLayout.14 7 Mar 2005 23:50:27 -0000 1.2 @@ -1,14 +1,14 @@ -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 +DEBUG [main] o.a.l.PatternLayoutTest: Message 0 +DEBUG [main] root: Message 0 +INFO [main] o.a.l.PatternLayoutTest: Message 1 +INFO [main] root: Message 1 +WARN [main] o.a.l.PatternLayoutTest: Message 2 +WARN [main] root: Message 2 +ERROR [main] o.a.l.PatternLayoutTest: Message 3 +ERROR [main] root: Message 3 +FATAL [main] o.a.l.PatternLayoutTest: Message 4 +FATAL [main] root: Message 4 +DEBUG [main] o.a.l.PatternLayoutTest: Message 5 java.lang.Exception: Just testing at org.apache.log4j.PatternLayoutTest.common(X) at org.apache.log4j.PatternLayoutTest.test14(X) @@ -21,7 +21,7 @@ at junit.framework.TestCase.run(X) at junit.framework.TestSuite.runTest(X) at junit.framework.TestSuite.run(X) - INFO 12 - Message 6 +INFO [main] o.a.l.PatternLayoutTest: Message 6 java.lang.Exception: Just testing at org.apache.log4j.PatternLayoutTest.common(X) at org.apache.log4j.PatternLayoutTest.test14(X) @@ -34,7 +34,7 @@ at junit.framework.TestCase.run(X) at junit.framework.TestSuite.runTest(X) at junit.framework.TestSuite.run(X) - WARN 13 - Message 7 +WARN [main] o.a.l.PatternLayoutTest: Message 7 java.lang.Exception: Just testing at org.apache.log4j.PatternLayoutTest.common(X) at org.apache.log4j.PatternLayoutTest.test14(X) @@ -47,7 +47,7 @@ at junit.framework.TestCase.run(X) at junit.framework.TestSuite.runTest(X) at junit.framework.TestSuite.run(X) -ERROR 14 - Message 8 +ERROR [main] o.a.l.PatternLayoutTest: Message 8 java.lang.Exception: Just testing at org.apache.log4j.PatternLayoutTest.common(X) at org.apache.log4j.PatternLayoutTest.test14(X) @@ -60,7 +60,7 @@ at junit.framework.TestCase.run(X) at junit.framework.TestSuite.runTest(X) at junit.framework.TestSuite.run(X) -FATAL 15 - Message 9 +FATAL [main] o.a.l.PatternLayoutTest: Message 9 java.lang.Exception: Just testing at org.apache.log4j.PatternLayoutTest.common(X) at org.apache.log4j.PatternLayoutTest.test14(X) --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]