package hu.sztaki.ilab.longneck.weblog.parser.processor;
import hu.sztaki.ilab.longneck.Field;
import hu.sztaki.ilab.longneck.Record;
import hu.sztaki.ilab.longneck.process.AbstractSourceInfoContainer;
import hu.sztaki.ilab.longneck.process.CheckError;
import hu.sztaki.ilab.longneck.process.block.BlockUtils;
import hu.sztaki.ilab.longneck.weblog.parser.postprocessor.CharcodingInterface;
import hu.sztaki.ilab.longneck.weblog.parser.postprocessor.PostProcessor;
import hu.sztaki.ilab.longneck.weblog.parser.postprocessor.PostProcessorFactory;
import hu.sztaki.ilab.longneck.weblog.parser.postprocessor.UrlParamsPostProcessor;
import java.util.InputMismatchException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.log4j.Logger;
import parser.PostProcessEnumType;
/**
* Parses and processes one log line based on the the configuration parameters.
*
* This implementation is thread-safe.
*
* @author Bendig LorĂ¡nd <lbendig@ilab.sztaki.hu>
*
*/
public class LogParser extends AbstractSourceInfoContainer {
public static final Logger LOG = Logger.getLogger(LogParser.class);
/** Compiled pattern to be applied on the log files. */
public final Pattern appliedPattern;
/** Unmodifiable list of log attributes. */
private final List<LogAttribute> attributesList;
/** The supposed character encoding of the logline. User can set this value in the config.xml.*/
String userdefined_charset = null;
/** The 2. supposed character encoding of the logline in the case when mixing encoding occur.
* User can set this value in the config.xml.*/
String userdefined_charset2 = null;
/** In case the Url parameter fields will add to the fields. */
Boolean creteUrlParameters = null;
/** Default value of caching when hadn't been defined by user is a config.xml. */
private static final boolean DEFAULT_CACHING = false;
public LogParser(String logLineRegexp, List<LogAttribute> attributesList) {
appliedPattern = Pattern.compile(logLineRegexp);
LOG.debug("LogParser logline pattern: " + appliedPattern.toString()) ;
this.attributesList = attributesList;
}
/** Constructor to be able to give user defined characterset(s).*/
public LogParser(String logLineRegexp, List<LogAttribute> attributesList, String userdefined_charset,
String userdefined_charset2, Boolean creteUrlParameters) {
appliedPattern = Pattern.compile(logLineRegexp);
LOG.debug("LogParser logline pattern: " + appliedPattern.toString()) ;
this.attributesList = attributesList;
this.userdefined_charset = userdefined_charset;
this.userdefined_charset2 = userdefined_charset2;
this.creteUrlParameters = creteUrlParameters;
}
/**
* Parses on log line based on the configuration parameters
*
* @param input - one log line
* @return Processed Record
* @throws CheckFailureException
*/
public void doProcess(Record result, String input) throws CheckError {
if (input == null) {
return;
}
Matcher m1 = appliedPattern.matcher(input);
if (!m1.matches() || attributesList.size() != m1.groupCount()) {
// Not match the line to expected format.
throw new InputMismatchException(String.format(
"Log format mismatch, weblog parser is unable to parse line:\n '%1$s'\n", input));
}
for (int i = 1; i != m1.groupCount() + 1; i++) {
String processedItem = m1.group(i);
LogAttribute logAttribute = attributesList.get(i - 1);
Field f = new Field(logAttribute.getAttributeAlias(), processedItem);
result.add(f);
List<ImmutablePostProcessType> postprocessors = logAttribute.getPostprocessors();
// Apply each log attribute postprocessor
for (ImmutablePostProcessType p : postprocessors) {
PostProcessEnumType pType = p.getType();
if (PostProcessEnumType.NONE != pType) {
PostProcessor postprocessor = PostProcessorFactory.get(pType);
String elementName = getElementName(logAttribute, p);
// Check if a given postprocessor implement a CharcodingInterface or not,
// than - if less one of the charactersets is setted - it will set the charactersets
// trought the CharcodingInterface.
if (postprocessor instanceof CharcodingInterface) {
((CharcodingInterface) postprocessor).setCharset(userdefined_charset);
((CharcodingInterface) postprocessor).setCharset2(userdefined_charset2);
}
// Set the createUrlParameter to the UrlParamsPostProcessor if it is given by user.
// The default is true.
if (postprocessor instanceof UrlParamsPostProcessor) {
((UrlParamsPostProcessor) postprocessor).setUserCreateParameterFiled(creteUrlParameters);
}
postprocessor.doPostProcess(elementName,
BlockUtils.getValue(elementName, result, null), p.getFieldList(),
result, p.isCaching() != null?p.isCaching():DEFAULT_CACHING);
}
}
}
}
/**
* Returns the name of the Field on which the postprocessor operates.
* If <apply-to-postfixed> is set on the given postprocessor (see logdefinition.xml)
* then its name is added as a postfix to the name of the log attribute. Otherwise the
* name log attribute is applied
*
* @param logAttribute Log attribute being processed
* @param p Postprocessor type
* @return The concatenated name.
*/
public static String getElementName(LogAttribute logAttribute,
ImmutablePostProcessType postProcessType) {
String postfixed = postProcessType.getApplyToPostfixed();
String attrName = logAttribute.getAttributeAlias();
return (postfixed == null) ? attrName : (attrName + postfixed);
}
}