package com.lightysoft.logmx.mgr.parsers;

 

import java.util.Date;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

import java.text.SimpleDateFormat;

 

import com.lightysoft.logmx.business.ParsedEntry;

import com.lightysoft.logmx.mgr.LogFileParser;

 

public class Log4jXMLLogFileParser extends LogFileParser {

    /** Current parsed log entry */

    private ParsedEntry entry = null;

 

    /** Pattern for entry begin */

    private final static Pattern ENTRY_BEGIN_PATTERN = Pattern

        .compile("^<log4j:event logger=\"(.*?)\" timestamp=\"(\\d*?)\" level=\"(.*?)\" thread=\"(.*?)\">$");

 

    /** Pattern String for entry message end */

    private final static String ENTRY_MSG_END = "(\\Q]]></log4j:message>\\E)?";

 

    /** Pattern for entry message begin */

    private final static Pattern ENTRY_MSG_BEGIN_PATTERN = Pattern

        .compile("^\\Q<log4j:message><![CDATA[\\E(.*?)" + ENTRY_MSG_END + "$");

 

    /** Pattern for entry message end */

    private final static Pattern ENTRY_MSG_END_PATTERN = Pattern.compile("^(.*?)" + ENTRY_MSG_END

            + "$");

 

    /** Date format for displayed entries */

    private final static SimpleDateFormat ENTRY_DATE_FORMAT = new SimpleDateFormat(

        "yyyy-MM-dd HH:mm:ss,SSS");

 

    /** Entry message buffer (used for better performance with very long entry message) */

    private StringBuilder entryMsgBuf = null;

 

 

    /**

     * Returns the name of this parser

     * @see com.lightysoft.logmx.mgr.LogFileParser#getParserName()

     */

    public String getParserName() {

        return "Log4jXMLParser";

    }

 

    /**

     * Returns the supported file type for this parser

     * @see com.lightysoft.logmx.mgr.LogFileParser#getSupportedFileType()

     */

    public String getSupportedFileType() {

        return "Log4j XML log file";

    }

 

    /**

     * Process the new line of text read from file

     * @see com.lightysoft.logmx.mgr.LogFileParser#parseLine(java.lang.String)

     */

    protected void parseLine(String line) throws Exception {

        // If end of file, records last entry if necessary, and exits

        if (line == null) {

            if (entry != null) {

                addParsedEntry(entry);

            }

            return;

        }

 

        Matcher matcher = ENTRY_BEGIN_PATTERN.matcher(line);

        if (matcher.matches()) {

            if (entry != null) { // record previous found entry if exists

                addParsedEntry(entry);

            }

 

            Date entryDate = new Date(Long.parseLong(matcher.group(2)));

 

            entryMsgBuf = new StringBuilder();

 

            entry = createNewEntry();

            entry.setEmitter(matcher.group(1));

            entry.setDate(ENTRY_DATE_FORMAT.format(entryDate));

            entry.setLevel(matcher.group(3));

            entry.setThread(matcher.group(4));

        } else if (entry != null) {

            matcher = ENTRY_MSG_BEGIN_PATTERN.matcher(line);

            if (matcher.matches()) {

                // Entry message begin

                entryMsgBuf.append(matcher.group(1));

            } else if (!line.equals("</log4j:event>")) {

                matcher = ENTRY_MSG_END_PATTERN.matcher(line);

                if (matcher.matches()) {

                    // Entry message, next part (may be the last)

                    entryMsgBuf.append("\n").append(matcher.group(1));

                }

            }

        }

    }

 

    /**

     * Send the parsed Entry to LogMX 

     */

    private void addParsedEntry(ParsedEntry pEntry) throws Exception {

        pEntry.setMessage(entryMsgBuf.toString());

        addEntry(pEntry);

    }

 

    /**

     * Returns the relative timestamp of given entry

     * @see com.lightysoft.logmx.mgr.LogFileParser#getRelativeEntryDate(com.lightysoft.logmx.business.ParsedEntry)

     */

    public Date getRelativeEntryDate(ParsedEntry pEntry) throws Exception {

        return getAbsoluteEntryDate(pEntry);

    }

 

    /**

     * Returns the relative timestamp of given entry 

     * @see com.lightysoft.logmx.mgr.LogFileParser#getAbsoluteEntryDate(com.lightysoft.logmx.business.ParsedEntry)

     */

    public Date getAbsoluteEntryDate(ParsedEntry pEntry) throws Exception {

        return ENTRY_DATE_FORMAT.parse(pEntry.getDate());

    }

}