/******************************************************************************* * 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.analyzer.internal.task; import java.util.List; import jsr166y.RecursiveAction; import net.sf.jacclog.api.LogEntryService; import net.sf.jacclog.api.domain.ReadableLogEntry; import net.sf.jacclog.api.domain.http.ReadableHttpRequestHeaderField; import net.sf.jacclog.api.domain.http.ReadableHttpResponseHeaderField; import net.sf.jacclog.service.analyzer.LogEntryAnalysisResult; import net.sf.jacclog.uasparser.UserAgentStringParser; import org.joda.time.Interval; public class AnalysisByIntervalTask extends RecursiveAction { private static final long serialVersionUID = 4387451272790339786L; protected static final int THRESHOLD = 200; private final Interval interval; private final int maxResults; private final UserAgentStringParser parser; private final LogEntryService<ReadableLogEntry<ReadableHttpRequestHeaderField, ReadableHttpResponseHeaderField>> service; private final LogEntryAnalysisResult.Builder builder; private final int startPosition; public AnalysisByIntervalTask( final LogEntryService<ReadableLogEntry<ReadableHttpRequestHeaderField, ReadableHttpResponseHeaderField>> service, final UserAgentStringParser parser, final LogEntryAnalysisResult.Builder builder, final Interval interval, final int startPosition, final int maxResults) { if (service == null) { throw new IllegalArgumentException("Argument 'service' can not be null."); } if (parser == null) { throw new IllegalArgumentException("Argument 'parser' can not be null."); } if (builder == null) { throw new IllegalArgumentException("Argument 'builder' can not be null."); } if (interval == null) { throw new IllegalArgumentException("Argument 'interval' can not be null."); } if (interval.getStart().isAfter(interval.getEndMillis())) { throw new IllegalArgumentException("The time interval specify an negative range."); } if (startPosition < 0) { throw new IllegalArgumentException("Argument 'startPosition' can not be smaller than 0."); } if (maxResults < 1) { throw new IllegalArgumentException("Argument 'maxResults' can not be smaller than 1."); } this.service = service; this.parser = parser; this.builder = builder; this.interval = interval; this.startPosition = startPosition; this.maxResults = maxResults; } @Override protected void compute() { if (maxResults < THRESHOLD) { final List<ReadableLogEntry<ReadableHttpRequestHeaderField, ReadableHttpResponseHeaderField>> entries = service .find(interval, startPosition, maxResults); if (entries != null && !entries.isEmpty()) { String userAgent = null; for (final ReadableLogEntry<ReadableHttpRequestHeaderField, ReadableHttpResponseHeaderField> entry : entries) { userAgent = AnalysisByEntriesTask.searchUserAgent(entry); if (userAgent != null) { builder.appendUserAgentInfo(parser.parse(userAgent)); } } } } else { final int midpoint = maxResults / 2; final AnalysisByIntervalTask a1 = new AnalysisByIntervalTask(service, parser, builder, interval, startPosition, midpoint); final AnalysisByIntervalTask a2 = new AnalysisByIntervalTask(service, parser, builder, interval, startPosition + midpoint, maxResults - midpoint); invokeAll(a1, a2); } } }