net.sf.logsaw.dialect.log4j.pattern.Log4JConversionPatternTranslator.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.logsaw.dialect.log4j.pattern.Log4JConversionPatternTranslator.java

Source

/*******************************************************************************
 * Copyright (c) 2010, 2011 LogSaw project and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    LogSaw project committers - initial API and implementation
 *******************************************************************************/
package net.sf.logsaw.dialect.log4j.pattern;

import java.text.DateFormat;
import java.text.DateFormatSymbols;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.sf.logsaw.core.dialect.ILogLevelProvider;
import net.sf.logsaw.core.field.ALogEntryField;
import net.sf.logsaw.core.field.Level;
import net.sf.logsaw.core.field.LogEntry;
import net.sf.logsaw.dialect.log4j.Log4JDialectPlugin;
import net.sf.logsaw.dialect.log4j.Log4JFieldProvider;
import net.sf.logsaw.dialect.log4j.internal.Messages;
import net.sf.logsaw.dialect.pattern.APatternDialect;
import net.sf.logsaw.dialect.pattern.ConversionRule;
import net.sf.logsaw.dialect.pattern.IConversionPatternTranslator;
import net.sf.logsaw.dialect.pattern.RegexUtils;

import org.apache.commons.io.IOUtils;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.osgi.util.NLS;

/**
 * This class can extract conversion rules out of a Log4J pattern.
 * 
 * @author Philipp Nanz
 */
public final class Log4JConversionPatternTranslator implements IConversionPatternTranslator {

    private static final Pattern EXTRACTION_PATTERN = Pattern
            .compile("%(-?(\\d+))?(\\.(\\d+))?([a-zA-Z])(\\{([^\\}]+)\\})?"); //$NON-NLS-1$
    private static final Pattern NEWLINE_PATTERN = Pattern.compile("%n"); //$NON-NLS-1$
    private static final String PROP_DATEFORMAT = "dateFormat"; //$NON-NLS-1$

    private int minLinesPerEntry;

    /* (non-Javadoc)
     * @see net.sf.logsaw.dialect.pattern.IConversionPatternTranslator#prepare(java.lang.String)
     */
    @Override
    public String prepare(String externalPattern) throws CoreException {
        if (!externalPattern.endsWith("%n")) { //$NON-NLS-1$
            throw new CoreException(new Status(IStatus.ERROR, Log4JDialectPlugin.PLUGIN_ID,
                    Messages.Log4JConversionRuleExtractor_error_mustEndWithNewLine));
        }
        // Pattern without %n
        externalPattern = externalPattern.substring(0, externalPattern.length() - 2);
        Matcher m = NEWLINE_PATTERN.matcher(externalPattern);
        minLinesPerEntry = 1;
        while (m.find()) {
            minLinesPerEntry++;
        }
        return externalPattern;
    }

    /* (non-Javadoc)
     * @see net.sf.logsaw.dialect.pattern.IConversionPatternTranslator#getMinLinesPerEntry()
     */
    @Override
    public int getMinLinesPerEntry() {
        return minLinesPerEntry;
    }

    /* (non-Javadoc)
     * @see net.sf.logsaw.dialect.pattern.IConversionPatternTranslator#applyLocale(java.util.Locale, java.util.List)
     */
    @Override
    public void applyLocale(Locale loc, List<ConversionRule> rules) {
        for (ConversionRule rule : rules) {
            if (rule.getPlaceholderName().equals("d")) { //$NON-NLS-1$
                SimpleDateFormat df = rule.getProperty(PROP_DATEFORMAT, SimpleDateFormat.class);
                Assert.isNotNull(df, "dateFormat"); //$NON-NLS-1$
                df.setDateFormatSymbols(DateFormatSymbols.getInstance(loc));
                return;
            }
        }
    }

    /* (non-Javadoc)
     * @see net.sf.logsaw.dialect.pattern.IConversionPatternTranslator#applyTimeZone(java.util.TimeZone, java.util.List)
     */
    @Override
    public void applyTimeZone(TimeZone tz, List<ConversionRule> rules) {
        for (ConversionRule rule : rules) {
            if (rule.getPlaceholderName().equals("d")) { //$NON-NLS-1$
                SimpleDateFormat df = rule.getProperty(PROP_DATEFORMAT, SimpleDateFormat.class);
                Assert.isNotNull(df, "dateFormat"); //$NON-NLS-1$
                df.setTimeZone(tz);
                return;
            }
        }
    }

    /* (non-Javadoc)
     * @see net.sf.logsaw.dialect.log4j.pattern.IConversionRuleExtractor#extractRules(java.lang.String)
     */
    @Override
    public List<ConversionRule> extractRules(String externalPattern) throws CoreException {
        // Find supported conversion characters
        Matcher m = EXTRACTION_PATTERN.matcher(externalPattern);
        List<ConversionRule> ret = new ArrayList<ConversionRule>();

        while (m.find()) {
            String minWidthModifier = m.group(2);
            String maxWidthModifier = m.group(4);
            String conversionName = m.group(5);
            String conversionModifier = m.group(7);

            int minWidth = -1; // not specified
            if ((minWidthModifier != null) && (minWidthModifier.length() > 0)) {
                minWidth = Integer.parseInt(minWidthModifier);
            }
            int maxWidth = -1; // not specified
            if ((maxWidthModifier != null) && (maxWidthModifier.length() > 0)) {
                maxWidth = Integer.parseInt(maxWidthModifier);
            }
            ConversionRule rule = new ConversionRule();
            rule.setBeginIndex(m.start());
            rule.setLength(m.end() - m.start());
            rule.setMaxWidth(maxWidth);
            rule.setMinWidth(minWidth);
            rule.setPlaceholderName(conversionName);
            rule.setModifier(conversionModifier);
            if (conversionName.equals("n")) {
                rule.setLineBreak(true);
            }
            ret.add(rule);
        }
        return ret;
    }

    /* (non-Javadoc)
     * @see net.sf.logsaw.dialect.pattern.IConversionPatternTranslator#applyDefaults(net.sf.logsaw.dialect.pattern.ConversionRule, net.sf.logsaw.dialect.pattern.APatternDialect)
     */
    @Override
    public void applyDefaults(ConversionRule rule, APatternDialect dialect) throws CoreException {
        if (rule.getPlaceholderName().equals("d") && (rule.getModifier() == null)) { //$NON-NLS-1$
            // ISO8601 is the default
            rule.setModifier("ISO8601"); //$NON-NLS-1$
        }
    }

    /* (non-Javadoc)
     * @see net.sf.logsaw.dialect.pattern.IConversionPatternTranslator#rewrite(net.sf.logsaw.dialect.pattern.ConversionRule, net.sf.logsaw.dialect.pattern.APatternDialect)
     */
    @Override
    public void rewrite(ConversionRule rule, APatternDialect dialect) throws CoreException {
        if (rule.getPlaceholderName().equals("d")) { //$NON-NLS-1$
            if (rule.getModifier().equals("ABSOLUTE")) { //$NON-NLS-1$
                rule.setModifier("HH:mm:ss,SSS"); //$NON-NLS-1$
            } else if (rule.getModifier().equals("DATE")) { //$NON-NLS-1$
                rule.setModifier("dd MMM yyyy HH:mm:ss,SSS"); //$NON-NLS-1$
            } else if (rule.getModifier().equals("ISO8601")) { //$NON-NLS-1$
                rule.setModifier("yyyy-MM-dd HH:mm:ss,SSS"); //$NON-NLS-1$
            }
            try {
                // Cache date format
                rule.putProperty(PROP_DATEFORMAT, new SimpleDateFormat(rule.getModifier()));
                dialect.configure(APatternDialect.OPTION_TIMESTAMP_PATTERN, rule.getModifier());
            } catch (IllegalArgumentException e) {
                throw new CoreException(new Status(IStatus.ERROR, Log4JDialectPlugin.PLUGIN_ID, NLS.bind(
                        Messages.Log4JConversionRuleTranslator_error_dataFormatNotSupported, rule.getModifier())));
            }
        }
    }

    /* (non-Javadoc)
     * @see net.sf.logsaw.dialect.log4j.pattern.IConversionRuleTranslator#convertToRegexPattern(net.sf.logsaw.dialect.log4j.pattern.ConversionRule)
     */
    @Override
    public String getRegexPatternForRule(ConversionRule rule) throws CoreException {
        if (rule.getPlaceholderName().equals("d")) { //$NON-NLS-1$
            // Pattern is dynamic
            return "(" + RegexUtils.getRegexForSimpleDateFormat(rule.getModifier()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
        } else if (rule.getPlaceholderName().equals("p")) { //$NON-NLS-1$
            String lnHint = RegexUtils.getLengthHint(rule);
            if (lnHint.length() > 0) {
                return "([ A-Z]" + lnHint + ")"; //$NON-NLS-1$ //$NON-NLS-2$
            }
            // Default: Length is limited by the levels available
            return "([A-Z]{4,5})"; //$NON-NLS-1$
        } else if (rule.getPlaceholderName().equals("c")) { //$NON-NLS-1$
            return "(.*" + RegexUtils.getLengthHint(rule) + RegexUtils.getLazySuffix(rule) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
        } else if (rule.getPlaceholderName().equals("t")) { //$NON-NLS-1$
            return "(.*" + RegexUtils.getLengthHint(rule) + RegexUtils.getLazySuffix(rule) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
        } else if (rule.getPlaceholderName().equals("m")) { //$NON-NLS-1$
            return "(.*" + RegexUtils.getLengthHint(rule) + RegexUtils.getLazySuffix(rule) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
        } else if (rule.getPlaceholderName().equals("n")) { //$NON-NLS-1$
            return "(" + IOUtils.LINE_SEPARATOR + ")"; //$NON-NLS-1$ //$NON-NLS-2$
        } else if (rule.getPlaceholderName().equals("F")) { //$NON-NLS-1$
            return "(.*" + RegexUtils.getLengthHint(rule) + RegexUtils.getLazySuffix(rule) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
        } else if (rule.getPlaceholderName().equals("C")) { //$NON-NLS-1$
            return "(.*" + RegexUtils.getLengthHint(rule) + RegexUtils.getLazySuffix(rule) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
        } else if (rule.getPlaceholderName().equals("M")) { //$NON-NLS-1$
            return "([a-zA-Z0-9]*" + RegexUtils.getLengthHint(rule) + RegexUtils.getLazySuffix(rule) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
        } else if (rule.getPlaceholderName().equals("L")) { //$NON-NLS-1$
            return "([0-9]*" + RegexUtils.getLengthHint(rule) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
        } else if (rule.getPlaceholderName().equals("x")) { //$NON-NLS-1$
            return "(.*" + RegexUtils.getLengthHint(rule) + RegexUtils.getLazySuffix(rule) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
        }
        throw new CoreException(new Status(IStatus.ERROR, Log4JDialectPlugin.PLUGIN_ID,
                NLS.bind(Messages.Log4JConversionRuleTranslator_error_unsupportedConversionCharacter,
                        rule.getPlaceholderName())));
    }

    /* (non-Javadoc)
     * @see net.sf.logsaw.dialect.log4j.pattern.IConversionRuleTranslator#getFieldForRule(net.sf.logsaw.dialect.log4j.pattern.ConversionRule)
     */
    @Override
    public ALogEntryField<?, ?> getFieldForRule(ConversionRule rule) throws CoreException {
        if (rule.getPlaceholderName().equals("d")) { //$NON-NLS-1$
            return Log4JFieldProvider.FIELD_TIMESTAMP;
        } else if (rule.getPlaceholderName().equals("p")) { //$NON-NLS-1$
            return Log4JFieldProvider.FIELD_LEVEL;
        } else if (rule.getPlaceholderName().equals("c")) { //$NON-NLS-1$
            return Log4JFieldProvider.FIELD_LOGGER;
        } else if (rule.getPlaceholderName().equals("t")) { //$NON-NLS-1$
            return Log4JFieldProvider.FIELD_THREAD;
        } else if (rule.getPlaceholderName().equals("m")) { //$NON-NLS-1$
            return Log4JFieldProvider.FIELD_MESSAGE;
        } else if (rule.getPlaceholderName().equals("n")) { //$NON-NLS-1$
            return null;
        } else if (rule.getPlaceholderName().equals("F")) { //$NON-NLS-1$
            return Log4JFieldProvider.FIELD_LOC_FILENAME;
        } else if (rule.getPlaceholderName().equals("C")) { //$NON-NLS-1$
            return Log4JFieldProvider.FIELD_LOC_CLASS;
        } else if (rule.getPlaceholderName().equals("M")) { //$NON-NLS-1$
            return Log4JFieldProvider.FIELD_LOC_METHOD;
        } else if (rule.getPlaceholderName().equals("L")) { //$NON-NLS-1$
            return Log4JFieldProvider.FIELD_LOC_LINE;
        } else if (rule.getPlaceholderName().equals("x")) { //$NON-NLS-1$
            return Log4JFieldProvider.FIELD_NDC;
        }
        throw new CoreException(new Status(IStatus.ERROR, Log4JDialectPlugin.PLUGIN_ID,
                NLS.bind(Messages.Log4JConversionRuleTranslator_error_unsupportedConversionCharacter,
                        rule.getPlaceholderName())));
    }

    /* (non-Javadoc)
     * @see net.sf.logsaw.dialect.log4j.pattern.IConversionRuleTranslator#extractField(net.sf.logsaw.core.model.LogEntry, net.sf.logsaw.dialect.log4j.pattern.ConversionRule, net.sf.logsaw.core.model.ALogEntryField, java.lang.String)
     */
    @Override
    public void extractField(LogEntry entry, ConversionRule rule, String val) throws CoreException {
        if (rule.getPlaceholderName().equals("d")) { //$NON-NLS-1$
            DateFormat df = rule.getProperty(PROP_DATEFORMAT, DateFormat.class);
            Assert.isNotNull(df, "dateFormat"); //$NON-NLS-1$
            try {
                entry.put(Log4JFieldProvider.FIELD_TIMESTAMP, df.parse(val.trim()));
            } catch (ParseException e) {
                throw new CoreException(new Status(IStatus.ERROR, Log4JDialectPlugin.PLUGIN_ID,
                        NLS.bind(Messages.Log4JConversionRuleTranslator_error_failedToParseTimestamp, val.trim())));
            }
        } else if (rule.getPlaceholderName().equals("p")) { //$NON-NLS-1$
            Level lvl = Log4JFieldProvider.FIELD_LEVEL.getLevelProvider().findLevel(val.trim());
            if (ILogLevelProvider.ID_LEVEL_UNKNOWN == lvl.getValue()) {
                throw new CoreException(new Status(IStatus.WARNING, Log4JDialectPlugin.PLUGIN_ID,
                        NLS.bind(Messages.Log4JConversionRuleTranslator_warning_unknownPriority, val.trim())));
            }
            entry.put(Log4JFieldProvider.FIELD_LEVEL, lvl);
        } else if (rule.getPlaceholderName().equals("c")) { //$NON-NLS-1$
            entry.put(Log4JFieldProvider.FIELD_LOGGER, val.trim());
        } else if (rule.getPlaceholderName().equals("t")) { //$NON-NLS-1$
            entry.put(Log4JFieldProvider.FIELD_THREAD, val.trim());
        } else if (rule.getPlaceholderName().equals("m")) { //$NON-NLS-1$
            entry.put(Log4JFieldProvider.FIELD_MESSAGE, val.trim());
        } else if (rule.getPlaceholderName().equals("n")) { //$NON-NLS-1$
            // nadda
        } else if (rule.getPlaceholderName().equals("F")) { //$NON-NLS-1$
            entry.put(Log4JFieldProvider.FIELD_LOC_FILENAME, val.trim());
        } else if (rule.getPlaceholderName().equals("C")) { //$NON-NLS-1$
            entry.put(Log4JFieldProvider.FIELD_LOC_CLASS, val.trim());
        } else if (rule.getPlaceholderName().equals("M")) { //$NON-NLS-1$
            entry.put(Log4JFieldProvider.FIELD_LOC_METHOD, val.trim());
        } else if (rule.getPlaceholderName().equals("L")) { //$NON-NLS-1$
            entry.put(Log4JFieldProvider.FIELD_LOC_LINE, val.trim());
        } else if (rule.getPlaceholderName().equals("x")) { //$NON-NLS-1$
            entry.put(Log4JFieldProvider.FIELD_NDC, val.trim());
        } else {
            throw new CoreException(new Status(IStatus.ERROR, Log4JDialectPlugin.PLUGIN_ID,
                    NLS.bind(Messages.Log4JConversionRuleTranslator_error_unsupportedConversionCharacter,
                            rule.getPlaceholderName())));
        }
    }
}