/******************************************************************************* * Copyright 2011 André Rouél * * Licensed 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 net.sf.jacclog.service.importer.internal.parser; import java.net.URI; import java.net.URISyntaxException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Map; import net.sf.jacclog.api.domain.LogEntryBuilder; import net.sf.jacclog.api.domain.http.HttpRequestHeader; import net.sf.jacclog.api.domain.http.HttpRequestHeaderField; import net.sf.jacclog.api.domain.http.HttpRequestMethod; import net.sf.jacclog.api.domain.http.HttpStatus; import net.sf.jacclog.logformat.LogFormat; import net.sf.jacclog.logformat.field.Field; import net.sf.jacclog.logformat.field.HttpLastStatusField; import net.sf.jacclog.logformat.field.HttpStatusField; import net.sf.jacclog.logformat.field.RemoteHostField; import net.sf.jacclog.logformat.field.RemoteUserField; import net.sf.jacclog.logformat.field.RequestFirstLineField; import net.sf.jacclog.logformat.field.RequestHeaderRefererField; import net.sf.jacclog.logformat.field.RequestHeaderUserAgentField; import net.sf.jacclog.logformat.field.RequestTimeField; import net.sf.jacclog.logformat.field.ResponseInBytesClfField; import net.sf.jacclog.logformat.field.ResponseInBytesField; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public final class TokensToLogEntryMapper { private static final Logger LOG = LoggerFactory.getLogger(TokensToLogEntryMapper.class); /** * <p> * Be aware if the size of tokens does not fit together with the set of fields an <code>MappingException</code> will * thrown. * </p> * * @param format * @param tokens * @return */ public static LogEntryBuilder map(final LogFormat format, final List<String> tokens) { if (format == null) { throw new IllegalArgumentException("Argument 'format' can not be null."); } if (tokens == null) { throw new IllegalArgumentException("Argument 'tokens' can not be null."); } if (tokens.size() != format.getFields().size()) { final StringBuilder buffer = new StringBuilder(100); buffer.append("The amount of tokens ("); buffer.append(tokens.size()); buffer.append(") will not fit together with the amount of fields ("); buffer.append(format.getFields().size()); buffer.append(")."); throw new MappingException(buffer.toString()); } final Map<Field, String> map = TokenToFieldMapper.map(format.getFields(), tokens); final LogEntryBuilder builder = new LogEntryBuilder(); mapHttpLastStatus(builder, map); mapHttpReferer(builder, map); mapHttpStatus(builder, map); mapRemoteHost(builder, map); mapRemoteUser(builder, map); mapRequestFirstLine(builder, map); mapRequestTime(builder, map); mapUserAgent(builder, map); mapResponseInBytesClf(builder, map); mapResponseInBytes(builder, map); return builder; } private static void mapHttpLastStatus(final LogEntryBuilder builder, final Map<Field, String> map) { if (map.containsKey(HttpLastStatusField.getInstance())) { try { final int status = Integer.parseInt(map.get(HttpLastStatusField.getInstance())); builder.lastStatusCode(HttpStatus.evaluate(status)); } catch (final NumberFormatException e) { // ignore this value } } } private static void mapHttpReferer(final LogEntryBuilder builder, final Map<Field, String> map) { if (map.containsKey(RequestHeaderRefererField.getInstance())) { final String referer = map.get(RequestHeaderRefererField.getInstance()); final HttpRequestHeaderField header = new HttpRequestHeaderField(HttpRequestHeader.REFERER, referer); builder.appendRequestHeaders(header); } } private static void mapHttpStatus(final LogEntryBuilder builder, final Map<Field, String> map) { if (map.containsKey(HttpStatusField.getInstance())) { try { final int status = Integer.parseInt(map.get(HttpStatusField.getInstance())); builder.statusCode(HttpStatus.evaluate(status)); } catch (final NumberFormatException e) { // ignore this value } } } private static void mapRemoteHost(final LogEntryBuilder builder, final Map<Field, String> map) { if (map.containsKey(RemoteHostField.getInstance())) { builder.remoteHost(map.get(RemoteHostField.getInstance())); } } private static void mapRemoteUser(final LogEntryBuilder builder, final Map<Field, String> map) { if (map.containsKey(RemoteUserField.getInstance())) { builder.remoteUser(map.get(RemoteUserField.getInstance())); } } private static void mapRequestFirstLine(final LogEntryBuilder builder, final Map<Field, String> map) { if (map.containsKey(RequestFirstLineField.getInstance())) { final String value = map.get(RequestFirstLineField.getInstance()); final String[] split = value.split("\\s"); if (split.length > 1) { builder.requestMethod(HttpRequestMethod.evaluate(split[0])); try { // TODO map more parts or create MetaData-Object final URI url = new URI(split[1]); builder.urlPath(url.getPath() != null ? url.getPath() : ""); builder.queryString(url.getQuery() != null ? url.getQuery() : ""); } catch (final URISyntaxException e) { LOG.info(e.getLocalizedMessage() + ": " + split[1]); } } } } private static void mapRequestTime(final LogEntryBuilder builder, final Map<Field, String> map) { if (map.containsKey(RequestTimeField.getInstance())) { Date requestTime; try { final SimpleDateFormat defaultTimeFormatter = new SimpleDateFormat("dd/MMM/yyyy:HH:mm:ss Z", Locale.ENGLISH); requestTime = defaultTimeFormatter.parse(map.get(RequestTimeField.getInstance())); builder.requestTime(requestTime); } catch (final ParseException e) { LOG.info(e.getLocalizedMessage() + ": " + map.get(RequestTimeField.getInstance())); // ignore this value } } } private static void mapResponseInBytes(final LogEntryBuilder builder, final Map<Field, String> map) { if (map.containsKey(ResponseInBytesField.getInstance())) { try { builder.responseInBytes(Long.parseLong(map.get(ResponseInBytesField.getInstance()))); } catch (final NumberFormatException e) { // ignore this value } } } private static void mapResponseInBytesClf(final LogEntryBuilder builder, final Map<Field, String> map) { if (map.containsKey(ResponseInBytesClfField.getInstance())) { final String bytesString = map.get(ResponseInBytesClfField.getInstance()); if (bytesString != null) { if ("-".equals(bytesString)) { builder.responseInBytes(Long.valueOf(0)); } else { try { builder.responseInBytes(Long.parseLong(bytesString)); } catch (final NumberFormatException e) { // ignore this value } } } } } private static void mapUserAgent(final LogEntryBuilder builder, final Map<Field, String> map) { if (map.containsKey(RequestHeaderUserAgentField.getInstance())) { final String userAgent = map.get(RequestHeaderUserAgentField.getInstance()); final HttpRequestHeaderField header = new HttpRequestHeaderField(HttpRequestHeader.USER_AGENT, userAgent); builder.appendRequestHeaders(header); } } private TokensToLogEntryMapper() { // stateless classes should not be instantiated } }