/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.varia;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.helpers.Constants;
import org.apache.log4j.plugins.Receiver;
import org.apache.log4j.rule.ExpressionRule;
import org.apache.log4j.rule.Rule;
import org.apache.log4j.spi.LocationInfo;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.ThrowableInformation;

/**
 * LogFilePatternReceiver can parse and tail log files, converting entries into
 * LoggingEvents.  If the file doesn't exist when the receiver is initialized, the
 * receiver will look for the file once every 10 seconds.
 * <p>
 * This receiver relies on java.util.regex features to perform the parsing of text in the
 * log file, however the only regular expression field explicitly supported is 
 * a glob-style wildcard used to ignore fields in the log file if needed.  All other
 * fields are parsed by using the supplied keywords.
 * <p>
 * <b>Features:</b><br>
 * - specify the URL of the log file to be processed<br>
 * - specify the timestamp format in the file (if one exists, using patterns from {@link java.text.SimpleDateFormat})<br>
 * - specify the pattern (logFormat) used in the log file using keywords, a wildcard character (*) and fixed text<br>
 * - 'tail' the file (allows the contents of the file to be continually read and new events processed)<br>
 * - supports the parsing of multi-line messages and exceptions
 * - 'hostname' property set to URL host (or 'file' if not available)
 * - 'application' property set to URL path (or value of fileURL if not available) 
 * - 'group' property can be set to associate multiple log file receivers
 *<p>
 * <b>Keywords:</b><br>
 * TIMESTAMP<br>
 * LOGGER<br>
 * LEVEL<br>
 * THREAD<br>
 * CLASS<br>
 * FILE<br>
 * LINE<br>
 * METHOD<br>
 * RELATIVETIME<br>
 * MESSAGE<br>
 * NDC<br>
 * PROP(key)<br>
 * (NL)<br>
 * <p>
 * (NL) represents a new line embedded in the log format, supporting log formats whose fields span multiple lines
 * <p>
 * Use a * to ignore portions of the log format that should be ignored
 * <p>
 * Example:<br>
 * If your file's patternlayout is this:<br>
 * <b>%d %-5p [%t] %C{2} (%F:%L) - %m%n</b>
 *<p>
 * specify this as the log format:<br>
 * <b>TIMESTAMP LEVEL [THREAD] CLASS (FILE:LINE) - MESSAGE</b>
 *<p>
 * To define a PROPERTY field, use PROP(key)
 * <p>
 * Example:<br> 
 * If you used the RELATIVETIME pattern layout character in the file, 
 * you can use PROP(RELATIVETIME) in the logFormat definition to assign 
 * the RELATIVETIME field as a property on the event.
 * <p>
 * If your file's patternlayout is this:<br>
 * <b>%r [%t] %-5p %c %x - %m%n</b>
 *<p>
 * specify this as the log format:<br>
 * <b>PROP(RELATIVETIME) [THREAD] LEVEL LOGGER * - MESSAGE</b>
 * <p>
 * Note the * - it can be used to ignore a single word or sequence of words in the log file
 * (in order for the wildcard to ignore a sequence of words, the text being ignored must be
 *  followed by some delimiter, like '-' or '[') - ndc is being ignored in the following example.
 * <p>
 * Assign a filterExpression in order to only process events which match a filter.
 * If a filterExpression is not assigned, all events are processed.
 *<p>
 * <b>Limitations:</b><br>
 * - no support for the single-line version of throwable supported by patternlayout<br>
 *   (this version of throwable will be included as the last line of the message)<br>
 * - the relativetime patternLayout character must be set as a property: PROP(RELATIVETIME)<br>
 * - messages should appear as the last field of the logFormat because the variability in message content<br>
 * - exceptions are converted if the exception stack trace (other than the first line of the exception)<br>
 *   is stored in the log file with a tab followed by the word 'at' as the first characters in the line<br>
 * - tailing may fail if the file rolls over. 
 *<p>
 * <b>Example receiver configuration settings</b> (add these as params, specifying a LogFilePatternReceiver 'plugin'):<br>
 * param: "timestampFormat" value="yyyy-MM-d HH:mm:ss,SSS"<br>
 * param: "logFormat" value="PROP(RELATIVETIME) [THREAD] LEVEL LOGGER * - MESSAGE"<br>
 * param: "fileURL" value="file:///c:/events.log"<br>
 * param: "tailing" value="true"
 *<p>
 * This configuration will be able to process these sample events:<br>
 * 710    [       Thread-0] DEBUG                   first.logger first - &lt;test&gt;   &lt;test2&gt;something here&lt;/test2&gt;   &lt;test3 blah=something/&gt;   &lt;test4&gt;       &lt;test5&gt;something else&lt;/test5&gt;   &lt;/test4&gt;&lt;/test&gt;<br>
 * 880    [       Thread-2] DEBUG                   first.logger third - &lt;test&gt;   &lt;test2&gt;something here&lt;/test2&gt;   &lt;test3 blah=something/&gt;   &lt;test4&gt;       &lt;test5&gt;something else&lt;/test5&gt;   &lt;/test4&gt;&lt;/test&gt;<br>
 * 880    [       Thread-0] INFO                    first.logger first - infomsg-0<br>
 * java.lang.Exception: someexception-first<br>
 *     at Generator2.run(Generator2.java:102)<br>
 *
 *@author Scott Deboy
 */
public class LogFilePatternReceiver extends Receiver {
  private final List keywords = new ArrayList();

  private static final String PROP_START = "PROP(";
  private static final String PROP_END = ")";

  private static final String LOGGER = "LOGGER";
  private static final String MESSAGE = "MESSAGE";
  private static final String TIMESTAMP = "TIMESTAMP";
  private static final String NDC = "NDC";
  private static final String LEVEL = "LEVEL";
  private static final String THREAD = "THREAD";
  private static final String CLASS = "CLASS";
  private static final String FILE = "FILE";
  private static final String LINE = "LINE";
  private static final String METHOD = "METHOD";
  private static final String NEWLINE = "(NL)";
  
  private static final String DEFAULT_HOST = "file";
  
  //all lines other than first line of exception begin with tab followed by 'at' followed by text
  private static final String EXCEPTION_PATTERN = "^\\s+at.*";
  private static final String REGEXP_DEFAULT_WILDCARD = ".*?";
  private static final String REGEXP_GREEDY_WILDCARD = ".*";
  private static final String PATTERN_WILDCARD = "*";
  //pull in optional leading and trailing spaces
  private static final String NOSPACE_GROUP = "(\\s*?\\S*?\\s*?)";
  private static final String DEFAULT_GROUP = "(" + REGEXP_DEFAULT_WILDCARD + ")";
  private static final String GREEDY_GROUP = "(" + REGEXP_GREEDY_WILDCARD + ")";
  private static final String MULTIPLE_SPACES_REGEXP = "[ ]+";
  private static final String NEWLINE_REGEXP = "\n";
  private final String newLine = System.getProperty("line.separator");

  private final String[] emptyException = new String[] { "" };

  private SimpleDateFormat dateFormat;
  private String timestampFormat;
  private String logFormat;
  private String customLevelDefinitions;
  private String fileURL;
  private String host;
  private String path;
  private boolean tailing;
  private String filterExpression;
  private long waitMillis = 2000; //default 2 seconds
  private String group;

  private static final String VALID_DATEFORMAT_CHARS = "GyYMwWDdFEuaHkKhmsSzZX";
  private static final String VALID_DATEFORMAT_CHAR_PATTERN = "[" + VALID_DATEFORMAT_CHARS + "]";

  private Rule expressionRule;

  private Map currentMap;
  private List additionalLines;
  private List matchingKeywords;

  private String regexp;
  private Reader reader;
  private Pattern regexpPattern;
  private Pattern exceptionPattern;
  private String timestampPatternText;

  private boolean useCurrentThread;
  public static final int MISSING_FILE_RETRY_MILLIS = 10000;
  private boolean appendNonMatches;
  private final Map customLevelDefinitionMap = new HashMap();

  //default to one line - this number is incremented for each (NL) found in the logFormat
  private int lineCount = 1;

    public LogFilePatternReceiver() {
    keywords.add(TIMESTAMP);
    keywords.add(LOGGER);
    keywords.add(LEVEL);
    keywords.add(THREAD);
    keywords.add(CLASS);
    keywords.add(FILE);
    keywords.add(LINE);
    keywords.add(METHOD);
    keywords.add(MESSAGE);
    keywords.add(NDC);
    try {
        exceptionPattern = Pattern.compile(EXCEPTION_PATTERN);
    } catch (PatternSyntaxException pse) {
        //shouldn't happen
    }
  }

  /**
   * Accessor
   * 
   * @return file URL
   */
  public String getFileURL() {
    return fileURL;
  }

  /**
   * Mutator
   * 
   * @param fileURL
   */
  public void setFileURL(String fileURL) {
    this.fileURL = fileURL;
  }

    /**
     * If the log file contains non-log4j level strings, they can be mapped to log4j levels using the format (android example):
     * V=TRACE,D=DEBUG,I=INFO,W=WARN,E=ERROR,F=FATAL,S=OFF
     *
     * @param customLevelDefinitions the level definition string
     */
  public void setCustomLevelDefinitions(String customLevelDefinitions) {
    this.customLevelDefinitions = customLevelDefinitions;
  }

  public String getCustomLevelDefinitions() {
    return customLevelDefinitions;
  }

  /**
   * Accessor
   * @return append non matches
   */
  public boolean isAppendNonMatches() {
      return appendNonMatches;
  }

  /**
   * Mutator
   * @param appendNonMatches
   */
  public void setAppendNonMatches(boolean appendNonMatches) {
      this.appendNonMatches = appendNonMatches;
  }

  /**
   * Accessor
   * 
   * @return filter expression
   */
  public String getFilterExpression() {
    return filterExpression;
  }

  /**
   * Mutator
   * 
   * @param filterExpression
   */
  public void setFilterExpression(String filterExpression) {
    this.filterExpression = filterExpression;
  }

  /**
   * Accessor
   * 
   * @return tailing
   */
  public boolean isTailing() {
    return tailing;
  }

  /**
   * Mutator
   * 
   * @param tailing
   */
  public void setTailing(boolean tailing) {
    this.tailing = tailing;
  }

  /**
   * When true, this property uses the current Thread to perform the import,
   * otherwise when false (the default), a new Thread is created and started to manage
   * the import.
   * @return
   */ 
 public final boolean isUseCurrentThread() {
     return useCurrentThread;
 }

 /**
  * Sets whether the current Thread or a new Thread is created to perform the import,
  * the default being false (new Thread created).
  * 
  * @param useCurrentThread
  */
 public final void setUseCurrentThread(boolean useCurrentThread) {
     this.useCurrentThread = useCurrentThread;
 }

  /**
   * Accessor
   * 
   * @return log format
   */
  public String getLogFormat() {
    return logFormat;
  }

    /**
   * Mutator
   *
   * @param logFormat
   *          the format
   */
  public void setLogFormat(String logFormat) {
    this.logFormat = logFormat;
  }

    /**
   * Mutator
   */
  public void setGroup(String group) { this.group = group; }


    /**
   * Accessor
   *
   * @return group
   */
  public String getGroup() { return group; }
    
    /**
   * Mutator.  Specify a pattern from {@link java.text.SimpleDateFormat}
   *
   * @param timestampFormat
   */
  public void setTimestampFormat(String timestampFormat) {
    this.timestampFormat = timestampFormat;
  }

    /**
   * Accessor
   *
   * @return timestamp format
   */
  public String getTimestampFormat() {
    return timestampFormat;
  }

  /**
   * Accessor
   * @return millis between retrieves of content
   */
  public long getWaitMillis() {
    return waitMillis;
  }

  /**
   * Mutator
   * @param waitMillis
   */
  public void setWaitMillis(long waitMillis) {
    this.waitMillis = waitMillis;
  }

    /**
   * Walk the additionalLines list, looking for the EXCEPTION_PATTERN.
   * <p>
   * Return the index of the first matched line
   * (the match may be the 1st line of an exception)
   * <p>
   * Assumptions: <br>
   * - the additionalLines list may contain both message and exception lines<br>
   * - message lines are added to the additionalLines list and then
   * exception lines (all message lines occur in the list prior to all
   * exception lines)
   *
   * @return -1 if no exception line exists, line number otherwise
   */
  private int getExceptionLine() {
    for (int i = 0; i < additionalLines.size(); i++) {
      Matcher exceptionMatcher = exceptionPattern.matcher((String)additionalLines.get(i));
      if (exceptionMatcher.matches()) {
        return i;
      }
    }
    return -1;
  }

    /**
   * Combine all message lines occuring in the additionalLines list, adding
   * a newline character between each line
   * <p>
   * the event will already have a message - combine this message
   * with the message lines in the additionalLines list
   * (all entries prior to the exceptionLine index)
   *
   * @param firstMessageLine primary message line
   * @param exceptionLine index of first exception line
   * @return message
   */
  private String buildMessage(String firstMessageLine, int exceptionLine) {
    if (additionalLines.size() == 0) {
      return firstMessageLine;
    }
    StringBuilder message = new StringBuilder();
    if (firstMessageLine != null) {
      message.append(firstMessageLine);
    }

    int linesToProcess = (exceptionLine == -1?additionalLines.size(): exceptionLine);

    for (int i = 0; i < linesToProcess; i++) {
      message.append(newLine);
      message.append(additionalLines.get(i));
    }
    return message.toString();
  }

    /**
   * Combine all exception lines occuring in the additionalLines list into a
   * String array
   * <p>
   * (all entries equal to or greater than the exceptionLine index)
   *
   * @param exceptionLine index of first exception line
   * @return exception
   */
  private String[] buildException(int exceptionLine) {
    if (exceptionLine == -1) {
      return emptyException;
    }
    String[] exception = new String[additionalLines.size() - exceptionLine - 1];
    for (int i = 0; i < exception.length; i++) {
      exception[i] = (String) additionalLines.get(i + exceptionLine);
    }
    return exception;
  }

    /**
   * Construct a logging event from currentMap and additionalLines
   * (additionalLines contains multiple message lines and any exception lines)
   * <p>
   * CurrentMap and additionalLines are cleared in the process
   *
   * @return event
   */
  private LoggingEvent buildEvent() {
    if (currentMap.size() == 0) {
      if (additionalLines.size() > 0) {
          for (Object additionalLine : additionalLines) {
              getLogger().debug("found non-matching line: " + additionalLine);
          }
      }
      additionalLines.clear();
      return null;
    }
    //the current map contains fields - build an event
    int exceptionLine = getExceptionLine();
    String[] exception = buildException(exceptionLine);

    //messages are listed before exceptions in additionallines
    if (additionalLines.size() > 0 && exception.length > 0) {
      currentMap.put(MESSAGE, buildMessage((String) currentMap.get(MESSAGE),
          exceptionLine));
    }
    LoggingEvent event = convertToEvent(currentMap, exception);
    currentMap.clear();
    additionalLines.clear();
    return event;
  }

    /**
   * Read, parse and optionally tail the log file, converting entries into logging events.
   *
   * A runtimeException is thrown if the logFormat pattern is malformed.
   *
   * @param bufferedReader
   * @throws IOException
   */
  protected void process(BufferedReader bufferedReader) throws IOException {
        Matcher eventMatcher;
        Matcher exceptionMatcher;
        String readLine;
        //if newlines are provided in the logFormat - (NL) - combine the lines prior to matching
        while ((readLine = bufferedReader.readLine()) != null) {
            StringBuilder line = new StringBuilder(readLine);
            //there is already one line (read above, start i at 1
            for (int i=1;i<lineCount;i++)
            {
                String thisLine = bufferedReader.readLine();
                if (thisLine != null)
                {
                  line.append(newLine).append(thisLine);
                }
            }
            String input = line.toString();
            eventMatcher = regexpPattern.matcher(input);
            //skip empty line entries
            if (input.trim().equals("")) {continue;}
            exceptionMatcher = exceptionPattern.matcher(input);
            if (eventMatcher.matches()) {
                //build an event from the previous match (held in current map)
                LoggingEvent event = buildEvent();
                if (event != null) {
                    if (passesExpression(event)) {
                        doPost(event);
                    }
                }
                currentMap.putAll(processEvent(eventMatcher.toMatchResult()));
            } else if (exceptionMatcher.matches()) {
                //an exception line
                additionalLines.add(input);
            } else {
                //neither...either post an event with the line or append as additional lines
                //if this was a logging event with multiple lines, each line will show up as its own event instead of being
                //appended as multiple lines on the same event..
                //choice is to have each non-matching line show up as its own line, or append them all to a previous event
                if (appendNonMatches) {
                    //hold on to the previous time, so we can do our best to preserve time-based ordering if the event is a non-match
                    String lastTime = (String)currentMap.get(TIMESTAMP);
                    //build an event from the previous match (held in current map)
                    if (currentMap.size() > 0) {
                        LoggingEvent event = buildEvent();
                        if (event != null) {
                            if (passesExpression(event)) {
                              doPost(event);
                            }
                        }
                    }
                    if (lastTime != null) {
                        currentMap.put(TIMESTAMP, lastTime);
                    }
                    currentMap.put(MESSAGE, input);
                } else {
                    additionalLines.add(input);
                }
            }
        }

        //process last event if one exists
        LoggingEvent event = buildEvent();
        if (event != null) {
            if (passesExpression(event)) {
                doPost(event);
            }
        }
    }

    protected void createPattern() {
        regexpPattern = Pattern.compile(regexp);
    }

    /**
   * Helper method that supports the evaluation of the expression
   *
   * @param event
   * @return true if expression isn't set, or the result of the evaluation otherwise
   */
  private boolean passesExpression(LoggingEvent event) {
    if (event != null) {
      if (expressionRule != null) {
        return (expressionRule.evaluate(event, null));
      }
    }
    return true;
  }

    /**
   * Convert the match into a map.
   * <p>
   * Relies on the fact that the matchingKeywords list is in the same
   * order as the groups in the regular expression
   *
   * @param result
   * @return map
   */
  private Map processEvent(MatchResult result) {
    Map map = new HashMap();
    //group zero is the entire match - process all other groups
    for (int i = 1; i < result.groupCount() + 1; i++) {
      Object key = matchingKeywords.get(i - 1);
      Object value = result.group(i);
      map.put(key, value);

    }
    return map;
  }

    /**
   * Helper method that will convert timestamp format to a pattern
   *
   *
   * @return string
   */
  private String convertTimestamp() {
    //some locales (for example, French) generate timestamp text with characters not included in \w -
    // now using \S (all non-whitespace characters) instead of /w
    String result = "";
    if (timestampFormat != null) {
      result = timestampFormat.replaceAll(Pattern.quote("+"), "[+]");
      result = result.replaceAll(VALID_DATEFORMAT_CHAR_PATTERN, "\\\\S+");
      //make sure dots in timestamp are escaped
      result = result.replaceAll(Pattern.quote("."), "\\\\.");
    }
    return result;
  }

    protected void setHost(String host) {
	  this.host = host;
  }

    protected void setPath(String path) {
	  this.path = path;
  }

  public String getPath() {
      return path;
  }

    /**
   * Build the regular expression needed to parse log entries
   *
   */
  protected void initialize() {
	if (host == null && path == null) {
		try {
			URL url = new URL(fileURL);
			host = url.getHost();
			path = url.getPath();
		} catch (MalformedURLException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}
	if (host == null || host.trim().equals("")) {
		host = DEFAULT_HOST;
	}
	if (path == null || path.trim().equals("")) {
		path = fileURL;
	}

    currentMap = new HashMap();
    additionalLines = new ArrayList();
    matchingKeywords = new ArrayList();

    if (timestampFormat != null) {
      dateFormat = new SimpleDateFormat(quoteTimeStampChars(timestampFormat));
      timestampPatternText = convertTimestamp();
    }
    //if custom level definitions exist, parse them
    updateCustomLevelDefinitionMap();
    try {
      if (filterExpression != null) {
        expressionRule = ExpressionRule.getRule(filterExpression);
      }
    } catch (Exception e) {
      getLogger().warn("Invalid filter expression: " + filterExpression, e);
    }

    List buildingKeywords = new ArrayList();

    String newPattern = logFormat;

    //process newlines - (NL) - in the logFormat - before processing properties
    int index = 0;
    while (index > -1) {
      index = newPattern.indexOf(NEWLINE);
      if (index > -1) {
        //keep track of number of expected newlines in the format, so the lines can be concatenated prior to matching
        lineCount++;
        newPattern = singleReplace(newPattern, NEWLINE, NEWLINE_REGEXP);
      }
    }
      
    String current = newPattern;
    //build a list of property names and temporarily replace the property with an empty string,
    //we'll rebuild the pattern later
    List propertyNames = new ArrayList();
    index = 0;
    while (index > -1) {
        if (current.contains(PROP_START) && current.contains(PROP_END)) {
            index = current.indexOf(PROP_START);
            String longPropertyName = current.substring(current.indexOf(PROP_START), current.indexOf(PROP_END) + 1);
            String shortProp = getShortPropertyName(longPropertyName);
            buildingKeywords.add(shortProp);
            propertyNames.add(longPropertyName);
            current = current.substring(longPropertyName.length() + 1 + index);
            newPattern = singleReplace(newPattern, longPropertyName, Integer.toString(buildingKeywords.size() - 1));
        } else {
            //no properties
            index = -1;
        }
    }

    /*
     * we're using a treemap, so the index will be used as the key to ensure
     * keywords are ordered correctly
     *
     * examine pattern, adding keywords to an index-based map patterns can
     * contain only one of these per entry...properties are the only 'keyword'
     * that can occur multiple times in an entry
     */
      for (Object keyword1 : keywords) {
          String keyword = (String) keyword1;
          int index2 = newPattern.indexOf(keyword);
          if (index2 > -1) {
              buildingKeywords.add(keyword);
              newPattern = singleReplace(newPattern, keyword, Integer.toString(buildingKeywords.size() - 1));
          }
      }

    StringBuilder buildingInt = new StringBuilder();

    for (int i=0;i<newPattern.length();i++) {
        String thisValue = String.valueOf(newPattern.substring(i, i+1));
        if (isInteger(thisValue)) {
            buildingInt.append(thisValue);
        } else {
            String stringInt = buildingInt.toString();
            if (isInteger(stringInt)) {
                matchingKeywords.add(buildingKeywords.get(Integer.parseInt(stringInt)));
            }
            //reset
            buildingInt.setLength(0);
        }
    }

    //if the very last value is an int, make sure to add it
      String stringInt = buildingInt.toString();
      if (isInteger(stringInt)) {
        matchingKeywords.add(buildingKeywords.get(Integer.parseInt(stringInt)));
    }

    newPattern = replaceMetaChars(newPattern);

    //compress one or more spaces in the pattern into the [ ]+ regexp
    //(supports padding of level in log files)
    newPattern = newPattern.replaceAll(MULTIPLE_SPACES_REGEXP, MULTIPLE_SPACES_REGEXP);
    newPattern = newPattern.replaceAll(Pattern.quote(PATTERN_WILDCARD), REGEXP_DEFAULT_WILDCARD);
    //use buildingKeywords here to ensure correct order
    for (int i = 0;i<buildingKeywords.size();i++) {
      String keyword = (String) buildingKeywords.get(i);
      //make the final keyword greedy (we're assuming it's the message)
      if (i == (buildingKeywords.size() - 1)) {
        newPattern = singleReplace(newPattern, String.valueOf(i), GREEDY_GROUP);
      } else if (TIMESTAMP.equals(keyword)) {
        newPattern = singleReplace(newPattern, String.valueOf(i), "(" + timestampPatternText + ")");
      } else if (LOGGER.equals(keyword) || LEVEL.equals(keyword)) {
        newPattern = singleReplace(newPattern, String.valueOf(i), NOSPACE_GROUP);
      } else {
        newPattern = singleReplace(newPattern, String.valueOf(i), DEFAULT_GROUP);
      }
    }

    regexp = newPattern;
    getLogger().debug("regexp is " + regexp);
  }

    private void updateCustomLevelDefinitionMap() {
        if (customLevelDefinitions != null) {
            StringTokenizer entryTokenizer = new StringTokenizer(customLevelDefinitions, ",");

            customLevelDefinitionMap.clear();
            while (entryTokenizer.hasMoreTokens()) {
                StringTokenizer innerTokenizer = new StringTokenizer(entryTokenizer.nextToken(), "=");
                customLevelDefinitionMap.put(innerTokenizer.nextToken(), Level.toLevel(innerTokenizer.nextToken()));
            }
        }
    }

    private boolean isInteger(String value) {
        try {
            Integer.parseInt(value);
            return true;
        } catch (NumberFormatException nfe) {
            return false;
        }
    }

    private String quoteTimeStampChars(String input) {
        //put single quotes around text that isn't a supported dateformat char
        StringBuilder result = new StringBuilder();
        //ok to default to false because we also check for index zero below
        boolean lastCharIsDateFormat = false;
        for (int i = 0;i<input.length();i++) {
            String thisVal = input.substring(i, i + 1);
            boolean thisCharIsDateFormat = VALID_DATEFORMAT_CHARS.contains(thisVal);
            //we have encountered a non-dateformat char
            if (!thisCharIsDateFormat && (i == 0 || lastCharIsDateFormat)) {
                result.append("'");
            }
            //we have encountered a dateformat char after previously encountering a non-dateformat char
            if (thisCharIsDateFormat && i > 0 && !lastCharIsDateFormat) {
                result.append("'");
            }
            lastCharIsDateFormat = thisCharIsDateFormat;
            result.append(thisVal);
        }
        //append an end single-quote if we ended with non-dateformat char
        if (!lastCharIsDateFormat) {
            result.append("'");
        }
        return result.toString();
    }

    private String singleReplace(String inputString, String oldString, String newString)
    {
        int propLength = oldString.length();
        int startPos = inputString.indexOf(oldString);
        if (startPos == -1)
        {
            getLogger().info("string: " + oldString + " not found in input: " + inputString + " - returning input");
            return inputString;
        }
        if (startPos == 0)
        {
            inputString = inputString.substring(propLength);
            inputString = newString + inputString;
        } else {
            inputString = inputString.substring(0, startPos) + newString + inputString.substring(startPos + propLength);
        }
        return inputString;
    }

    private String getShortPropertyName(String longPropertyName)
  {
      String currentProp = longPropertyName.substring(longPropertyName.indexOf(PROP_START));
      String prop = currentProp.substring(0, currentProp.indexOf(PROP_END) + 1);
      String shortProp = prop.substring(PROP_START.length(), prop.length() - 1);
      return shortProp;
  }

    /**
   * Some perl5 characters may occur in the log file format.
   * Escape these characters to prevent parsing errors.
   *
   * @param input
   * @return string
   */
  private String replaceMetaChars(String input) {
    //escape backslash first since that character is used to escape the remaining meta chars
    input = input.replaceAll("\\\\", "\\\\\\");

    //don't escape star - it's used as the wildcard
    input = input.replaceAll(Pattern.quote("]"), "\\\\]");
    input = input.replaceAll(Pattern.quote("["), "\\\\[");
    input = input.replaceAll(Pattern.quote("^"), "\\\\^");
    input = input.replaceAll(Pattern.quote("$"), "\\\\$");
    input = input.replaceAll(Pattern.quote("."), "\\\\.");
    input = input.replaceAll(Pattern.quote("|"), "\\\\|");
    input = input.replaceAll(Pattern.quote("?"), "\\\\?");
    input = input.replaceAll(Pattern.quote("+"), "\\\\+");
    input = input.replaceAll(Pattern.quote("("), "\\\\(");
    input = input.replaceAll(Pattern.quote(")"), "\\\\)");
    input = input.replaceAll(Pattern.quote("-"), "\\\\-");
    input = input.replaceAll(Pattern.quote("{"), "\\\\{");
    input = input.replaceAll(Pattern.quote("}"), "\\\\}");
    input = input.replaceAll(Pattern.quote("#"), "\\\\#");
    return input;
  }

    /**
   * Convert a keyword-to-values map to a LoggingEvent
   *
   * @param fieldMap
   * @param exception
   *
   * @return logging event
   */
  private LoggingEvent convertToEvent(Map fieldMap, String[] exception) {
    if (fieldMap == null) {
      return null;
    }

    //a logger must exist at a minimum for the event to be processed
    if (!fieldMap.containsKey(LOGGER)) {
      fieldMap.put(LOGGER, "Unknown");
    }
    if (exception == null) {
      exception = emptyException;
    }

    Logger logger;
    long timeStamp = 0L;
    String level;
    String threadName;
    Object message;
    String ndc;
    String className;
    String methodName;
    String eventFileName;
    String lineNumber;
    Hashtable properties = new Hashtable();

    logger = Logger.getLogger((String) fieldMap.remove(LOGGER));

    if ((dateFormat != null) && fieldMap.containsKey(TIMESTAMP)) {
      try {
        timeStamp = dateFormat.parse((String) fieldMap.remove(TIMESTAMP))
            .getTime();
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
    //use current time if timestamp not parseable/dateformat not specified
    if (timeStamp == 0L) {
      timeStamp = System.currentTimeMillis();
    }

    message = fieldMap.remove(MESSAGE);
    if (message == null) {
      message = "";
    }

    level = (String) fieldMap.remove(LEVEL);
    Level levelImpl;
    if (level == null) {
        levelImpl = Level.DEBUG;
    } else {
        //first try to resolve against custom level definition map, then fall back to regular levels
        levelImpl = (Level) customLevelDefinitionMap.get(level);
        if (levelImpl == null) {
            levelImpl = Level.toLevel(level.trim());
            if (!level.equals(levelImpl.toString())) {
                //check custom level map
                if (levelImpl == null) {
                    levelImpl = Level.DEBUG;
                    getLogger().debug("found unexpected level: " + level + ", logger: " + logger.getName() + ", msg: " + message);
                    //make sure the text that couldn't match a level is added to the message
                    message = level + " " + message;
                }
            }
        }
    }

    threadName = (String) fieldMap.remove(THREAD);

    ndc = (String) fieldMap.remove(NDC);

    className = (String) fieldMap.remove(CLASS);

    methodName = (String) fieldMap.remove(METHOD);

    eventFileName = (String) fieldMap.remove(FILE);

    lineNumber = (String) fieldMap.remove(LINE);

    properties.put(Constants.HOSTNAME_KEY, host);
    properties.put(Constants.APPLICATION_KEY, path);
    properties.put(Constants.RECEIVER_NAME_KEY, getName());
    if (group != null) {
        properties.put(Constants.GROUP_KEY, group);
    }

    //all remaining entries in fieldmap are properties
    properties.putAll(fieldMap);

    LocationInfo info;

    if ((eventFileName != null) || (className != null) || (methodName != null)
        || (lineNumber != null)) {
      info = new LocationInfo(eventFileName, className, methodName, lineNumber);
    } else {
      info = LocationInfo.NA_LOCATION_INFO;
    }

    LoggingEvent event = new LoggingEvent(null,
            logger, timeStamp, levelImpl, message,
            threadName,
            new ThrowableInformation(exception),
            ndc,
            info,
            properties);

    return event;
  }

//  public static void main(String[] args) {
//    org.apache.log4j.Logger rootLogger = org.apache.log4j.Logger.getRootLogger();
//    org.apache.log4j.ConsoleAppender appender = new org.apache.log4j.ConsoleAppender(new org.apache.log4j.SimpleLayout());
//    appender.setName("console");
//    rootLogger.addAppender(appender);
//    LogFilePatternReceiver test = new LogFilePatternReceiver();
//    org.apache.log4j.spi.LoggerRepository repo = new org.apache.log4j.LoggerRepositoryExImpl(org.apache.log4j.LogManager.getLoggerRepository());
//    test.setLoggerRepository(repo);
//    test.setLogFormat("PROP(RELATIVETIME) [THREAD] LEVEL LOGGER * - MESSAGE");
//    test.setTailing(false);
//    test.setAppendNonMatches(true);
//    test.setTimestampFormat("yyyy-MM-d HH:mm:ss,SSS");
//    test.setFileURL("file:///C:/log/test.log");
//    test.activateOptions();
//  }

    /**
   * Close the reader.
   */
  public void shutdown() {
    getLogger().info(getPath() + " shutdown");
    active = false;
    try {
      if (reader != null) {
        reader.close();
        reader = null;
      }
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }
  }

    /**
   * Read and process the log file.
   */
  public void activateOptions() {
    getLogger().info("activateOptions");
    active = true;
	Runnable runnable = new Runnable() {
	  public void run() {
        initialize();
            while (reader == null) {
                getLogger().info("attempting to load file: " + getFileURL());
                try {
                    reader = new InputStreamReader(new URL(getFileURL()).openStream(), "UTF-8");
                } catch (FileNotFoundException fnfe) {
                    getLogger().info("file not available - will try again");
                    synchronized (this) {
                        try {
                            wait(MISSING_FILE_RETRY_MILLIS);
                        } catch (InterruptedException ie) {}
                    }
                } catch (IOException ioe) {
                    getLogger().warn("unable to load file", ioe);
                    return;
                }
            }
            try {
                BufferedReader bufferedReader = new BufferedReader(reader);
                createPattern();
                do {
                    process(bufferedReader);
                    try {
                        synchronized (this) {
                            wait(waitMillis);
                        }
                    } catch (InterruptedException ie) {}
                    if (tailing) {
                      getLogger().debug("tailing file");
                    }
                } while (tailing);

            } catch (IOException ioe) {
                //io exception - probably shut down
                getLogger().info("stream closed");
            }
            getLogger().debug("processing " + path + " complete");
            shutdown();
          }
        };
        if(useCurrentThread) {
            runnable.run();
        }else {
            new Thread(runnable, "LogFilePatternReceiver-"+getName()).start();
        }
    }
}
