/*
 * 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.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

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;
import org.apache.oro.text.perl.Perl5Util;
import org.apache.oro.text.regex.MalformedPatternException;
import org.apache.oro.text.regex.MatchResult;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;

/**
 * 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 ORO Perl5 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) 
 *<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>
 * <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 this 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="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 - <test>   <test2>something here</test2>   <test3 blah=something/>   <test4>       <test5>something else</test5>   </test4></test><br>
 * 880    [       Thread-2] DEBUG                   first.logger third - <test>   <test2>something here</test2>   <test3 blah=something/>   <test4>       <test5>something else</test5>   </test4></test><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 Set keywords = new HashSet();

  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 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 = "\tat.*";
  private static final String REGEXP_DEFAULT_WILDCARD = ".+?";
  private static final String REGEXP_GREEDY_WILDCARD = ".+";
  private static final String PATTERN_WILDCARD = "*";
  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 final String newLine = System.getProperty("line.separator");

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

  private SimpleDateFormat dateFormat;
  private String timestampFormat = "yyyy-MM-d HH:mm:ss,SSS";
  private String logFormat;
  private String fileURL;
  private String host;
  private String path;
  private boolean tailing;
  private String filterExpression;

  private Perl5Util util = null;
  private Perl5Compiler exceptionCompiler = null;
  private Perl5Matcher exceptionMatcher = null;
  private static final String VALID_DATEFORMAT_CHAR_PATTERN = "[GyMwWDdFEaHkKhmsSzZ]";

  private Rule expressionRule;

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

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

private boolean useCurrentThread;

  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);
  }

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

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

  /**
   * 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.  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;
  }

  /**
   * Walk the additionalLines list, looking for the EXCEPTION_PATTERN.
   * <p>
   * Return the index of the first matched line minus 1 
   * (the match is the 2nd 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() {
    try {
      Pattern exceptionPattern = exceptionCompiler.compile(EXCEPTION_PATTERN);
      for (int i = 0; i < additionalLines.size(); i++) {
        if (exceptionMatcher.matches((String) additionalLines.get(i), exceptionPattern)) {
          return i - 1;
        }
      }
    } catch (MalformedPatternException mpe) {
      getLogger().warn("Bad pattern: " + EXCEPTION_PATTERN);
    }
    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 || exceptionLine == 0) {
      return firstMessageLine;
    }
    StringBuffer message = new StringBuffer();
    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];
    for (int i = 0; i < additionalLines.size() - exceptionLine; 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 (Iterator iter = additionalLines.iterator();iter.hasNext();) {
          getLogger().info("found non-matching line: " + iter.next());
        }
      }
      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 && exceptionLine != 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 
   * according to ORO's Perl5Compiler.
   * 
   * @param unbufferedReader
   * @throws IOException
   */
  protected void process(BufferedReader bufferedReader) throws IOException {

        Perl5Matcher eventMatcher = new Perl5Matcher();
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            if (eventMatcher.matches(line, regexpPattern)) {
                //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.getMatch()));
            } else {
                //getLogger().debug("line doesn't match pattern - must be ")
                //may be an exception or additional message lines
                additionalLines.add(line);
            }
        }

        //process last event if one exists
        LoggingEvent event = buildEvent();
        if (event != null) {
            if (passesExpression(event)) {
                doPost(event);
            }
            getLogger().debug("no further lines to process in " + fileURL);
        }
    }

    /**
     * create the regular expression pattern using the input regular expression
     */
    protected void createPattern() {
        Perl5Compiler compiler = new Perl5Compiler();
        try {
            regexpPattern = compiler.compile(regexp);
        } catch (MalformedPatternException mpe) {
            throw new RuntimeException("Bad pattern: " + 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));
      }
    }
    return true;
  }

  /**
   * Convert the ORO 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.groups(); i++) {
      map.put(matchingKeywords.get(i - 1), result.group(i));
    }
    return map;
  }
  
  /**
   * Helper method that will convert timestamp format to a pattern
   * 
   * 
   * @return string
   */
  private String convertTimestamp() {
    return util.substitute("s/("+VALID_DATEFORMAT_CHAR_PATTERN+")+/\\\\w+/g", timestampFormat);
  }
  
  protected void setHost(String host) {
	  this.host = host;
  }
  
  protected void setPath(String path) {
	  this.path = 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;
	}
	
    util = new Perl5Util();
    exceptionCompiler = new Perl5Compiler();
    exceptionMatcher = new Perl5Matcher();

    currentMap = new HashMap();
    additionalLines = new ArrayList();
    matchingKeywords = new ArrayList();
    
    if (timestampFormat != null) {
      dateFormat = new SimpleDateFormat(timestampFormat);
      timestampPatternText = convertTimestamp();
    }

    try {
      if (filterExpression != null) {
        expressionRule = ExpressionRule.getRule(filterExpression);
      }
    } catch (Exception e) {
      getLogger().warn("Invalid filter expression: " + filterExpression, e);
    }

    Map keywordMap = new TreeMap();

    String newPattern = logFormat;

    /*
     * examine pattern, adding properties to an index-based map where the key is the 
     * numeric offset from the start of the pattern so that order can be preserved
     * 
     * Replaces PROP(X) definitions in the pattern with the short version X, so 
     * that the name can be used as the event property later 
     */
    int index = 0;
    int currentPosition = 0;
    String current = newPattern;
    while (index > -1) {
      index = current.indexOf(PROP_START);
      currentPosition = currentPosition + index;
      if (index > -1) {
        String currentProp = current.substring(current.indexOf(PROP_START));
        String prop = currentProp.substring(0,
            currentProp.indexOf(PROP_END) + 1);
        current = current.substring(current.indexOf(currentProp) + 1);
        String shortProp = prop.substring(PROP_START.length(),
            prop.length() - 1);
        keywordMap.put(new Integer(currentPosition), shortProp);
        newPattern = replace(prop, shortProp, newPattern);
      }
    }

    newPattern = replaceMetaChars(newPattern);

    //compress one or more spaces in the pattern into the [ ]+ regexp
    //(supports padding of level in log files)
    newPattern = util.substitute("s/" + MULTIPLE_SPACES_REGEXP +"/" + MULTIPLE_SPACES_REGEXP + "/g", newPattern);
    newPattern = replace(PATTERN_WILDCARD, REGEXP_DEFAULT_WILDCARD, newPattern);

    /*
     * 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
     */
    Iterator iter = keywords.iterator();
    while (iter.hasNext()) {
      String keyword = (String) iter.next();
      int index2 = newPattern.indexOf(keyword);
      if (index2 > -1) {
        keywordMap.put(new Integer(index2), keyword);
      }
    }

    //keywordMap should be ordered by index..add all values to a list
    matchingKeywords.addAll(keywordMap.values());

    /*
     * iterate over the keywords found in the pattern and replace with regexp
     * group
     */
    String currentPattern = newPattern;
    for (int i = 0;i<matchingKeywords.size();i++) {
      String keyword = (String) matchingKeywords.get(i);
      //make the final keyword greedy
      if (i == (matchingKeywords.size() - 1)) {
        currentPattern = replace(keyword, GREEDY_GROUP, currentPattern);
      } else if (TIMESTAMP.equals(keyword)) {
        currentPattern = replace(keyword, "(" + timestampPatternText + ")", currentPattern);
      } else {
        currentPattern = replace(keyword, DEFAULT_GROUP, currentPattern);
      }
    }

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

  /**
   * Helper method that will globally replace a section of text
   * 
   * @param pattern
   * @param replacement
   * @param input 
   * 
   * @return string
   */
  private String replace(String pattern, String replacement, String input) {
    return util.substitute("s/" + Perl5Compiler.quotemeta(pattern) + "/"
        + Perl5Compiler.quotemeta(replacement) + "/g", input);
  }

  /**
   * 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) {
    input = replace("(", "\\(", input);
    input = replace(")", "\\)", input);
    input = replace("[", "\\[", input);
    input = replace("]", "\\]", input);
    input = replace("{", "\\{", input);
    input = replace("}", "\\}", input);
    input = replace("#", "\\#", input);
    input = replace("/", "\\/", input);
    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 = null;
    long timeStamp = 0L;
    String level = null;
    String threadName = null;
    Object message = null;
    String ndc = null;
    String className = null;
    String methodName = null;
    String eventFileName = null;
    String lineNumber = null;
    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
    if (timeStamp == 0L) {
      timeStamp = System.currentTimeMillis();
    }

    level = (String) fieldMap.remove(LEVEL);
    Level levelImpl = (level == null ? Level.DEBUG : Level.toLevel(level.trim()));

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

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

    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());

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

    LocationInfo info = null;

    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) {
    /*
    LogFilePatternReceiver test = new LogFilePatternReceiver();
    test.setLogFormat("TIMESTAMP LEVEL [THREAD] LOGGER (FILE:LINE) - MESSAGE");
    test.setTailing(true);
    test.setFileURL("file:///C:/log/test.log");
    test.initialize();
    try {
      test.process(new InputStreamReader(new URL(test.getFileURL())
          .openStream()));
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }
    */
  }

  /**
   * Close the reader. 
   */
  public void shutdown() {
    try {
      if (reader != null) {
        reader.close();
        reader = null;
      }
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }
  }

  /**
   * Read and process the log file.
   */
  public void activateOptions() {
	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());
                    } catch (FileNotFoundException fnfe) {
                        getLogger().info("file not available - will try again in 10 seconds");
                        synchronized (this) {
                            try {
                                wait(10000);
                            } catch (InterruptedException ie) {}
                        }
                    } catch (IOException ioe) {
                        getLogger().warn("unable to load file", ioe);
                        return;
                    }
                }
                try {
                    BufferedReader bufferedReader = new BufferedReader(reader);
                    createPattern();
                    do {
                        getLogger().debug("tailing file: " + tailing);
                        process(bufferedReader);
                        try {
                            synchronized (this) {
                                wait(2000);
                            }
                        } catch (InterruptedException ie) {
                        }
                    } while (tailing);

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