FileDocCategorySizeDatePackage
PatternParser.javaAPI DocApache log4j 1.2.1515720Sat Aug 25 00:09:40 BST 2007org.apache.log4j.helpers

PatternParser

public class PatternParser extends Object
Most of the work of the {@link org.apache.log4j.PatternLayout} class is delegated to the PatternParser class.

It is this class that parses conversion patterns and creates a chained list of {@link OptionConverter OptionConverters}.

author
James P. Cakalic
author
Ceki Gülcü
author
Anders Kristensen
since
0.8.2

Fields Summary
private static final char
ESCAPE_CHAR
private static final int
LITERAL_STATE
private static final int
CONVERTER_STATE
private static final int
DOT_STATE
private static final int
MIN_STATE
private static final int
MAX_STATE
static final int
FULL_LOCATION_CONVERTER
static final int
METHOD_LOCATION_CONVERTER
static final int
CLASS_LOCATION_CONVERTER
static final int
LINE_LOCATION_CONVERTER
static final int
FILE_LOCATION_CONVERTER
static final int
RELATIVE_TIME_CONVERTER
static final int
THREAD_CONVERTER
static final int
LEVEL_CONVERTER
static final int
NDC_CONVERTER
static final int
MESSAGE_CONVERTER
int
state
protected StringBuffer
currentLiteral
protected int
patternLength
protected int
i
PatternConverter
head
PatternConverter
tail
protected FormattingInfo
formattingInfo
protected String
pattern
Constructors Summary
public PatternParser(String pattern)


  
    
    this.pattern = pattern;
    patternLength =  pattern.length();
    state = LITERAL_STATE;
  
Methods Summary
protected voidaddConverter(org.apache.log4j.helpers.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();
  
private voidaddToList(org.apache.log4j.helpers.PatternConverter pc)

    if(head == null) {
      head = tail = pc;
    } else {
      tail.next = pc;
      tail = pc;
    }
  
protected java.lang.StringextractOption()

    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;
  
protected intextractPrecisionOption()
The option is expected to be in decimal and positive. In case of error, zero is returned.

    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;
  
protected voidfinalizeConverter(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);
  
public org.apache.log4j.helpers.PatternConverterparse()

    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;