merge in refactoring of top programs

This commit is contained in:
Greg DiCristofaro
2020-09-30 16:11:56 -04:00
87 changed files with 820 additions and 424 deletions
@@ -173,7 +173,7 @@ class UnpackagePortableCaseProgressDialog extends javax.swing.JDialog implements
throw new TskCoreException("Error finding 7-Zip executable"); // NON-NLS
}
String outputFolderSwitch = "-o" + String.format("\"%s\"",outputFolder); // NON-NLS
String outputFolderSwitch = String.format("\"-o%s\"",outputFolder); // NON-NLS
ProcessBuilder procBuilder = new ProcessBuilder();
procBuilder.command(
String.format("\"%s\"",sevenZipExe.getAbsolutePath()),
@@ -119,6 +119,8 @@ public final class IconsUtil {
imageFile = "validationFailed.png"; //NON-NLS
} else if (typeID == ARTIFACT_TYPE.TSK_WEB_ACCOUNT_TYPE.getTypeID()) {
imageFile = "web-account-type.png"; //NON-NLS
} else if (typeID == ARTIFACT_TYPE.TSK_WEB_FORM_ADDRESS.getTypeID()) {
imageFile = "web-form-address.png"; //NON-NLS
} else {
imageFile = "artifact-icon.png"; //NON-NLS
}
@@ -398,6 +398,20 @@ final class DataSourceInfoUtilities {
BlackboardAttribute attr = getAttributeOrNull(artifact, attributeType);
return (attr == null) ? null : attr.getValueLong();
}
/**
* Retrieves the int value of a certain attribute type from an artifact.
*
* @param artifact The artifact.
* @param attributeType The attribute type.
*
* @return The 'getValueInt()' value or null if the attribute could not be
* retrieved.
*/
static Integer getIntOrNull(BlackboardArtifact artifact, Type attributeType) {
BlackboardAttribute attr = getAttributeOrNull(artifact, attributeType);
return (attr == null) ? null : attr.getValueInt();
}
/**
* Retrieves the long value of a certain attribute type from an artifact and
@@ -1,370 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* 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 org.sleuthkit.autopsy.datasourcesummary.datamodel;
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor;
import java.io.File;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.commons.lang.StringUtils;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Provides information to populate Top Programs Summary queries.
*/
public class TopProgramsSummary implements DefaultArtifactUpdateGovernor {
private static final Set<Integer> ARTIFACT_UPDATE_TYPE_IDS = new HashSet<>(Arrays.asList(
ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID()
));
/**
* A SQL join type.
*/
private enum JoinType {
LEFT,
RIGHT,
INNER,
OUTER
}
/**
* A blackboard attribute value column.
*/
private enum AttributeColumn {
value_text,
value_int32,
value_int64
}
/**
* The suffix joined to a key name for use as an identifier of a query.
*/
private static final String QUERY_SUFFIX = "_query";
/**
* Functions that determine the folder name of a list of path elements. If
* not matched, function returns null.
*/
private static final List<Function<List<String>, String>> SHORT_FOLDER_MATCHERS = Arrays.asList(
// handle Program Files and Program Files (x86) - if true, return the next folder
(pathList) -> {
if (pathList.size() < 2) {
return null;
}
String rootParent = pathList.get(0).toUpperCase();
if ("PROGRAM FILES".equals(rootParent) || "PROGRAM FILES (X86)".equals(rootParent)) {
return pathList.get(1);
} else {
return null;
}
},
// if there is a folder named "APPLICATION DATA" or "APPDATA"
(pathList) -> {
for (String pathEl : pathList) {
String uppered = pathEl.toUpperCase();
if ("APPLICATION DATA".equals(uppered) || "APPDATA".equals(uppered)) {
return "AppData";
}
}
return null;
}
);
/**
* Creates a sql statement querying the blackboard attributes table for a
* particular attribute type and returning a specified value. That query
* also joins with the blackboard artifact table.
*
* @param joinType The type of join statement to create.
* @param attributeColumn The blackboard attribute column that should be
* returned.
* @param attrType The attribute type to query for.
* @param keyName The aliased name of the attribute to return. This
* is also used to calculate the alias of the query
* same as getFullKey.
* @param bbaName The blackboard artifact table alias.
*
* @return The generated sql statement.
*/
private static String getAttributeJoin(JoinType joinType, AttributeColumn attributeColumn, BlackboardAttribute.ATTRIBUTE_TYPE attrType, String keyName, String bbaName) {
String queryName = keyName + QUERY_SUFFIX;
String innerQueryName = "inner_attribute_" + queryName;
return "\n" + joinType + " JOIN (\n"
+ " SELECT \n"
+ " " + innerQueryName + ".artifact_id,\n"
+ " " + innerQueryName + "." + attributeColumn + " AS " + keyName + "\n"
+ " FROM blackboard_attributes " + innerQueryName + "\n"
+ " WHERE " + innerQueryName + ".attribute_type_id = " + attrType.getTypeID() + " -- " + attrType.name() + "\n"
+ ") " + queryName + " ON " + queryName + ".artifact_id = " + bbaName + ".artifact_id\n";
}
/**
* Given a column key, creates the full name for the column key.
*
* @param key The column key.
*
* @return The full identifier for the column key.
*/
private static String getFullKey(String key) {
return key + QUERY_SUFFIX + "." + key;
}
/**
* Constructs a SQL 'where' statement from a list of clauses and puts
* parenthesis around each clause.
*
* @param clauses The clauses
*
* @return The generated 'where' statement.
*/
private static String getWhereString(List<String> clauses) {
if (clauses.isEmpty()) {
return "";
}
List<String> parenthesized = clauses.stream()
.map(c -> "(" + c + ")")
.collect(Collectors.toList());
return "\nWHERE " + String.join("\n AND ", parenthesized) + "\n";
}
/**
* Generates a [column] LIKE sql clause.
*
* @param column The column identifier.
* @param likeString The string that will be used as column comparison.
* @param isLike if false, the statement becomes NOT LIKE.
*
* @return The generated statement.
*/
private static String getLikeClause(String column, String likeString, boolean isLike) {
return column + (isLike ? "" : " NOT") + " LIKE '" + likeString + "'";
}
private final SleuthkitCaseProvider provider;
public TopProgramsSummary() {
this(SleuthkitCaseProvider.DEFAULT);
}
public TopProgramsSummary(SleuthkitCaseProvider provider) {
this.provider = provider;
}
@Override
public Set<Integer> getArtifactTypeIdsForRefresh() {
return ARTIFACT_UPDATE_TYPE_IDS;
}
/**
* Retrieves a list of the top programs used on the data source. Currently
* determines this based off of which prefetch results return the highest
* count.
*
* @param dataSource The data source.
* @param count The number of programs to return.
*
* @return The top results objects found.
*
* @throws SleuthkitCaseProviderException
* @throws TskCoreException
* @throws SQLException
*/
public List<TopProgramsResult> getTopPrograms(DataSource dataSource, int count)
throws SleuthkitCaseProviderException, TskCoreException, SQLException {
if (dataSource == null || count <= 0) {
return Collections.emptyList();
}
// ntosboot should be ignored
final String ntosBootIdentifier = "NTOSBOOT";
// programs in windows directory to be ignored
final String windowsDir = "/WINDOWS%";
final String nameParam = "name";
final String pathParam = "path";
final String runCountParam = "run_count";
final String lastRunParam = "last_run";
String bbaQuery = "bba";
final String query = "SELECT\n"
+ " " + getFullKey(nameParam) + " AS " + nameParam + ",\n"
+ " " + getFullKey(pathParam) + " AS " + pathParam + ",\n"
+ " MAX(" + getFullKey(runCountParam) + ") AS " + runCountParam + ",\n"
+ " MAX(" + getFullKey(lastRunParam) + ") AS " + lastRunParam + "\n"
+ "FROM blackboard_artifacts " + bbaQuery + "\n"
+ getAttributeJoin(JoinType.INNER, AttributeColumn.value_text, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, nameParam, bbaQuery)
+ getAttributeJoin(JoinType.LEFT, AttributeColumn.value_text, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH, pathParam, bbaQuery)
+ getAttributeJoin(JoinType.LEFT, AttributeColumn.value_int32, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COUNT, runCountParam, bbaQuery)
+ getAttributeJoin(JoinType.LEFT, AttributeColumn.value_int64, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, lastRunParam, bbaQuery)
+ getWhereString(Arrays.asList(
bbaQuery + ".artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID(),
bbaQuery + ".data_source_obj_id = " + dataSource.getId(),
// exclude ntosBootIdentifier from results
getLikeClause(getFullKey(nameParam), ntosBootIdentifier, false),
// exclude windows directory items from results
getFullKey(pathParam) + " IS NULL OR " + getLikeClause(getFullKey(pathParam), windowsDir, false)
))
+ "GROUP BY " + getFullKey(nameParam) + ", " + getFullKey(pathParam) + "\n"
+ "ORDER BY \n"
+ " MAX(" + getFullKey(runCountParam) + ") DESC,\n"
+ " MAX(" + getFullKey(lastRunParam) + ") DESC,\n"
+ " " + getFullKey(nameParam) + " ASC";
DataSourceInfoUtilities.ResultSetHandler<List<TopProgramsResult>> handler = (resultSet) -> {
List<TopProgramsResult> progResults = new ArrayList<>();
boolean quitAtCount = false;
while (resultSet.next() && (!quitAtCount || progResults.size() < count)) {
long lastRunEpoch = resultSet.getLong(lastRunParam);
Date lastRun = (resultSet.wasNull()) ? null : new Date(lastRunEpoch * 1000);
Long runCount = resultSet.getLong(runCountParam);
if (resultSet.wasNull()) {
runCount = null;
}
if (lastRun != null || runCount != null) {
quitAtCount = true;
}
progResults.add(new TopProgramsResult(
resultSet.getString(nameParam),
resultSet.getString(pathParam),
runCount,
lastRun));
}
return progResults;
};
try (SleuthkitCase.CaseDbQuery dbQuery = provider.get().executeQuery(query);
ResultSet resultSet = dbQuery.getResultSet()) {
return handler.process(resultSet);
}
}
/**
* Determines a short folder name if any. Otherwise, returns empty string.
*
* @param strPath The string path.
* @param applicationName The application name.
*
* @return The short folder name or empty string if not found.
*/
public String getShortFolderName(String strPath, String applicationName) {
if (strPath == null) {
return "";
}
List<String> pathEls = new ArrayList<>(Arrays.asList(applicationName));
File file = new File(strPath);
while (file != null && StringUtils.isNotBlank(file.getName())) {
pathEls.add(file.getName());
file = file.getParentFile();
}
Collections.reverse(pathEls);
for (Function<List<String>, String> matchEntry : SHORT_FOLDER_MATCHERS) {
String result = matchEntry.apply(pathEls);
if (StringUtils.isNotBlank(result)) {
return result;
}
}
return "";
}
/**
* Describes a result of a program run on a datasource.
*/
public static class TopProgramsResult {
private final String programName;
private final String programPath;
private final Long runTimes;
private final Date lastRun;
/**
* Main constructor.
*
* @param programName The name of the program.
* @param programPath The path of the program.
* @param runTimes The number of runs.
*/
TopProgramsResult(String programName, String programPath, Long runTimes, Date lastRun) {
this.programName = programName;
this.programPath = programPath;
this.runTimes = runTimes;
this.lastRun = lastRun;
}
/**
* @return The name of the program
*/
public String getProgramName() {
return programName;
}
/**
* @return The path of the program.
*/
public String getProgramPath() {
return programPath;
}
/**
* @return The number of run times or null if not present.
*/
public Long getRunTimes() {
return runTimes;
}
/**
* @return The last time the program was run or null if not present.
*/
public Date getLastRun() {
return lastRun;
}
}
}
@@ -18,6 +18,7 @@
*/
package org.sleuthkit.autopsy.datasourcesummary.datamodel;
import java.io.File;
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor;
import java.util.ArrayList;
import java.util.Arrays;
@@ -30,6 +31,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -54,6 +56,36 @@ import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
*/
public class UserActivitySummary implements DefaultArtifactUpdateGovernor {
/**
* Functions that determine the folder name of a list of path elements. If
* not matched, function returns null.
*/
private static final List<Function<List<String>, String>> SHORT_FOLDER_MATCHERS = Arrays.asList(
// handle Program Files and Program Files (x86) - if true, return the next folder
(pathList) -> {
if (pathList.size() < 2) {
return null;
}
String rootParent = pathList.get(0).toUpperCase();
if ("PROGRAM FILES".equals(rootParent) || "PROGRAM FILES (X86)".equals(rootParent)) {
return pathList.get(1);
} else {
return null;
}
},
// if there is a folder named "APPLICATION DATA" or "APPDATA"
(pathList) -> {
for (String pathEl : pathList) {
String uppered = pathEl.toUpperCase();
if ("APPLICATION DATA".equals(uppered) || "APPDATA".equals(uppered)) {
return "AppData";
}
}
return null;
}
);
private static final BlackboardArtifact.Type TYPE_DEVICE_ATTACHED = new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED);
private static final BlackboardArtifact.Type TYPE_WEB_HISTORY = new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_WEB_HISTORY);
@@ -69,17 +101,51 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor {
private static final BlackboardAttribute.Type TYPE_DATETIME_START = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_START);
private static final BlackboardAttribute.Type TYPE_DATETIME_END = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_END);
private static final BlackboardAttribute.Type TYPE_DOMAIN = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DOMAIN);
private static final BlackboardAttribute.Type TYPE_PROG_NAME = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME);
private static final BlackboardAttribute.Type TYPE_PATH = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH);
private static final BlackboardAttribute.Type TYPE_COUNT = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_COUNT);
private static final String NTOS_BOOT_IDENTIFIER = "NTOSBOOT";
private static final String WINDOWS_PREFIX = "/WINDOWS";
private static final Comparator<TopAccountResult> TOP_ACCOUNT_RESULT_DATE_COMPARE = (a, b) -> a.getLastAccess().compareTo(b.getLastAccess());
private static final Comparator<TopWebSearchResult> TOP_WEBSEARCH_RESULT_DATE_COMPARE = (a, b) -> a.getDateAccessed().compareTo(b.getDateAccessed());
/**
* Sorts TopProgramsResults pushing highest run time count then most recent
* run and then the program name that comes earliest in the alphabet.
*/
private static final Comparator<TopProgramsResult> TOP_PROGRAMS_RESULT_COMPARE = (a, b) -> {
// first priority for sorting is the run times
// if non-0, this is the return value for the comparator
int runTimesCompare = nullableCompare(a.getRunTimes(), b.getRunTimes());
if (runTimesCompare != 0) {
return -runTimesCompare;
}
// second priority for sorting is the last run date
// if non-0, this is the return value for the comparator
int lastRunCompare = nullableCompare(
a.getLastRun() == null ? null : a.getLastRun().getTime(),
b.getLastRun() == null ? null : b.getLastRun().getTime());
if (lastRunCompare != 0) {
return -lastRunCompare;
}
// otherwise sort alphabetically
return (a.getProgramName() == null ? "" : a.getProgramName())
.compareToIgnoreCase((b.getProgramName() == null ? "" : b.getProgramName()));
};
private static final Set<Integer> ARTIFACT_UPDATE_TYPE_IDS = new HashSet<>(Arrays.asList(
ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID(),
ARTIFACT_TYPE.TSK_MESSAGE.getTypeID(),
ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(),
ARTIFACT_TYPE.TSK_CALLLOG.getTypeID(),
ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID(),
ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID()
ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID(),
ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID()
));
private static final Set<String> DEVICE_EXCLUDE_LIST = new HashSet<>(Arrays.asList("ROOT_HUB", "ROOT_HUB20"));
@@ -539,6 +605,188 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor {
.collect(Collectors.toList());
}
/**
* Determines a short folder name if any. Otherwise, returns empty string.
*
* @param strPath The string path.
* @param applicationName The application name.
*
* @return The short folder name or empty string if not found.
*/
public String getShortFolderName(String strPath, String applicationName) {
if (strPath == null) {
return "";
}
List<String> pathEls = new ArrayList<>(Arrays.asList(applicationName));
File file = new File(strPath);
while (file != null && org.apache.commons.lang.StringUtils.isNotBlank(file.getName())) {
pathEls.add(file.getName());
file = file.getParentFile();
}
Collections.reverse(pathEls);
for (Function<List<String>, String> matchEntry : SHORT_FOLDER_MATCHERS) {
String result = matchEntry.apply(pathEls);
if (org.apache.commons.lang.StringUtils.isNotBlank(result)) {
return result;
}
}
return "";
}
/**
* Creates a TopProgramsResult from a TSK_PROG_RUN blackboard artifact.
*
* @param artifact The TSK_PROG_RUN blackboard artifact.
*
* @return The generated TopProgramsResult.
*/
private TopProgramsResult getTopProgramsResult(BlackboardArtifact artifact) {
String programName = DataSourceInfoUtilities.getStringOrNull(artifact, TYPE_PROG_NAME);
String path = DataSourceInfoUtilities.getStringOrNull(artifact, TYPE_PATH);
// ignore items with no name or a ntos boot identifier
if (StringUtils.isBlank(programName) || NTOS_BOOT_IDENTIFIER.equalsIgnoreCase(programName)) {
return null;
}
// ignore windows directory
if (StringUtils.startsWithIgnoreCase(path, WINDOWS_PREFIX)) {
return null;
}
Integer count = DataSourceInfoUtilities.getIntOrNull(artifact, TYPE_COUNT);
Long longCount = (count == null) ? null : (long) count;
return new TopProgramsResult(
programName,
path,
longCount,
DataSourceInfoUtilities.getDateOrNull(artifact, TYPE_DATETIME)
);
}
/**
* Retrieves the maximum date given two (possibly null) dates.
*
* @param date1 First date.
* @param date2 Second date.
*
* @return The maximum non-null date or null if both items are null.
*/
private static Date getMax(Date date1, Date date2) {
if (date1 == null) {
return date2;
} else if (date2 == null) {
return date1;
} else {
return date1.compareTo(date2) > 0 ? date1 : date2;
}
}
/**
* Returns the compare value favoring the higher non-null number.
*
* @param long1 First possibly null long.
* @param long2 Second possibly null long.
*
* @return Returns the compare value: 1,0,-1 favoring the higher non-null
* value.
*/
private static int nullableCompare(Long long1, Long long2) {
if (long1 == null && long2 == null) {
return 0;
} else if (long1 != null && long2 == null) {
return 1;
} else if (long1 == null && long2 != null) {
return -1;
}
return Long.compare(long1, long2);
}
/**
* Returns true if number is non-null and higher than 0.
*
* @param longNum The number.
*
* @return True if non-null and higher than 0.
*/
private static boolean isPositiveNum(Long longNum) {
return longNum != null && longNum > 0;
}
/**
* Retrieves the top programs results for the given data source limited to
* the count provided as a parameter. The highest run times are at the top
* of the list. If that information isn't available the last run date is
* used. If both, the last run date and the number of run times are
* unavailable, the programs will be sorted alphabetically, the count will
* be ignored and all items will be returned.
*
* @param dataSource The datasource. If the datasource is null, an empty
* list will be returned.
* @param count The number of results to return. This value must be > 0
* or an IllegalArgumentException will be thrown.
*
* @return The sorted list and limited to the count if last run or run count
* information is available on any item.
*
* @throws SleuthkitCaseProviderException
* @throws TskCoreException
*/
public List<TopProgramsResult> getTopPrograms(DataSource dataSource, int count) throws SleuthkitCaseProviderException, TskCoreException {
assertValidCount(count);
if (dataSource == null) {
return Collections.emptyList();
}
// Get TopProgramsResults for each TSK_PROG_RUN artifact
Collection<TopProgramsResult> results = caseProvider.get().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID(), dataSource.getId())
.stream()
// convert to a TopProgramsResult object or null if missing critical information
.map((art) -> getTopProgramsResult(art))
// remove any null items
.filter((res) -> res != null)
// group by the program name and program path
// The value will be a TopProgramsResult with the max run times
// and most recent last run date for each program name / program path pair.
.collect(Collectors.toMap(
res -> Pair.of(res.getProgramName(), res.getProgramPath()),
res -> res,
(res1, res2) -> {
return new TopProgramsResult(
res1.getProgramName(),
res1.getProgramPath(),
getMax(res1.getRunTimes(), res2.getRunTimes()),
getMax(res1.getLastRun(), res2.getLastRun()));
})).values();
List<TopProgramsResult> orderedResults = results.stream()
.sorted(TOP_PROGRAMS_RESULT_COMPARE)
.collect(Collectors.toList());
// only limit the list to count if there is no last run date and no run times.
if (orderedResults.size() > 0) {
TopProgramsResult topResult = orderedResults.get(0);
// if run times / last run information is available, the first item should have some value,
// and then the items should be limited accordingly.
if (isPositiveNum(topResult.getRunTimes())
|| (topResult.getLastRun() != null && isPositiveNum(topResult.getLastRun().getTime()))) {
return orderedResults.stream().limit(count).collect(Collectors.toList());
}
}
// otherwise return the alphabetized list with no limit applied.
return orderedResults;
}
/**
* Object containing information about a web search artifact.
*/
@@ -722,4 +970,57 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor {
return lastVisit;
}
}
/**
* Describes a result of a program run on a datasource.
*/
public static class TopProgramsResult {
private final String programName;
private final String programPath;
private final Long runTimes;
private final Date lastRun;
/**
* Main constructor.
*
* @param programName The name of the program.
* @param programPath The path of the program.
* @param runTimes The number of runs.
*/
TopProgramsResult(String programName, String programPath, Long runTimes, Date lastRun) {
this.programName = programName;
this.programPath = programPath;
this.runTimes = runTimes;
this.lastRun = lastRun;
}
/**
* @return The name of the program
*/
public String getProgramName() {
return programName;
}
/**
* @return The path of the program.
*/
public String getProgramPath() {
return programPath;
}
/**
* @return The number of run times or null if not present.
*/
public Long getRunTimes() {
return runTimes;
}
/**
* @return The last time the program was run or null if not present.
*/
public Date getLastRun() {
return lastRun;
}
}
}
@@ -29,12 +29,11 @@ import org.apache.commons.lang.StringUtils;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.IngestModuleCheckUtil;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.TopProgramsSummary;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopAccountResult;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDeviceAttachedResult;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopWebSearchResult;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.TopProgramsSummary.TopProgramsResult;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDomainsResult;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopProgramsResult;
import org.sleuthkit.autopsy.datasourcesummary.uiutils.CellModelTableCellRenderer.DefaultCellModel;
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents;
import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel;
@@ -227,35 +226,30 @@ public class UserActivityPanel extends BaseDataSourceSummaryPanel {
private final IngestRunningLabel ingestRunningLabel = new IngestRunningLabel();
private final List<DataFetchComponents<DataSource, ?>> dataFetchComponents;
private final TopProgramsSummary topProgramsData;
private final UserActivitySummary userActivityData;
/**
* Creates a new UserActivityPanel.
*/
public UserActivityPanel() {
this(new TopProgramsSummary(), new UserActivitySummary());
this(new UserActivitySummary());
}
/**
* Creates a new UserActivityPanel.
*
* @param topProgramsData Class from which to obtain top programs data.
* @param userActivityData Class from which to obtain remaining user
* activity data.
*/
public UserActivityPanel(
TopProgramsSummary topProgramsData,
UserActivitySummary userActivityData) {
super(topProgramsData, userActivityData);
this.topProgramsData = topProgramsData;
public UserActivityPanel(UserActivitySummary userActivityData) {
super(userActivityData);
this.userActivityData = userActivityData;
// set up data acquisition methods
this.dataFetchComponents = Arrays.asList(
// top programs query
new DataFetchComponents<DataSource, List<TopProgramsResult>>(
(dataSource) -> topProgramsData.getTopPrograms(dataSource, TOP_PROGS_COUNT),
(dataSource) -> userActivityData.getTopPrograms(dataSource, TOP_PROGS_COUNT),
(result) -> {
showResultWithModuleCheck(topProgramsTable, result,
IngestModuleCheckUtil.RECENT_ACTIVITY_FACTORY,
@@ -307,7 +301,7 @@ public class UserActivityPanel extends BaseDataSourceSummaryPanel {
* @return The underlying short folder name if one exists.
*/
private String getShortFolderName(String path, String appName) {
return this.topProgramsData.getShortFolderName(path, appName);
return this.userActivityData.getShortFolderName(path, appName);
}
@Override
@@ -140,7 +140,7 @@ public class DataFetchWorker<A, R> extends SwingWorker<R, Void> {
}
// and pass the result to the client
resultHandler.accept(DataFetchResult.getErrorResult(inner));
resultHandler.accept(DataFetchResult.getErrorResult(ex.getCause()));
return;
}
@@ -26,6 +26,7 @@ import java.util.Map;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.SleuthkitCase;
/**
@@ -35,12 +36,14 @@ public class DomainSearch {
private final DomainSearchCache searchCache;
private final DomainSearchThumbnailCache thumbnailCache;
private final DomainSearchArtifactsCache artifactsCache;
/**
* Construct a new DomainSearch object.
*/
public DomainSearch() {
this(new DomainSearchCache(), new DomainSearchThumbnailCache());
this(new DomainSearchCache(), new DomainSearchThumbnailCache(),
new DomainSearchArtifactsCache());
}
/**
@@ -51,9 +54,11 @@ public class DomainSearch {
* @param thumbnailCache The DomainSearchThumnailCache to use for this
* DomainSearch.
*/
DomainSearch(DomainSearchCache cache, DomainSearchThumbnailCache thumbnailCache) {
DomainSearch(DomainSearchCache cache, DomainSearchThumbnailCache thumbnailCache,
DomainSearchArtifactsCache artifactsCache) {
this.searchCache = cache;
this.thumbnailCache = thumbnailCache;
this.artifactsCache = artifactsCache;
}
/**
@@ -139,17 +144,40 @@ public class DomainSearch {
}
/**
* Get a thumbnail representation of a domain name. See
* DomainSearchThumbnailRequest for more details.
* Get a thumbnail representation of a domain name.
*
* Thumbnail candidates are JPEG files that have either TSK_WEB_DOWNLOAD or
* TSK_WEB_CACHE artifacts that match the domain name (see the DomainSearch
* getArtifacts() API). JPEG files are sorted by most recent if sourced from
* TSK_WEB_DOWNLOADs and by size if sourced from TSK_WEB_CACHE artifacts.
* The first suitable thumbnail is selected.
*
* @param thumbnailRequest Thumbnail request for domain.
*
* @return An Image instance or null if no thumbnail is available.
* @return A thumbnail of the first matching JPEG, or a default thumbnail if
* no suitable JPEG exists.
*
* @throws DiscoveryException If there is an error with Discovery related
* processing.
* processing.
*/
public Image getThumbnail(DomainSearchThumbnailRequest thumbnailRequest) throws DiscoveryException {
return thumbnailCache.get(thumbnailRequest);
}
/**
* Get all blackboard artifacts that match the requested domain name.
*
* Artifacts will be selected if the requested domain name is either an
* exact match on a TSK_DOMAIN value or a substring match on a TSK_URL
* value. String matching is case insensitive.
*
* @param artifactsRequest The request containing the case, artifact type,
* and domain name.
* @return A list of blackboard artifacts that match the request criteria.
* @throws DiscoveryException If an exception is encountered during
* processing.
*/
public List<BlackboardArtifact> getArtifacts(DomainSearchArtifactsRequest artifactsRequest) throws DiscoveryException {
return artifactsCache.get(artifactsRequest);
}
}
@@ -47,6 +47,11 @@ public class DomainSearchArtifactsCache {
* process.
*/
public List<BlackboardArtifact> get(DomainSearchArtifactsRequest request) throws DiscoveryException {
String typeName = request.getArtifactType().getLabel();
if (!typeName.startsWith("TSK_WEB")) {
throw new IllegalArgumentException("Only web artifacts are valid arguments");
}
try {
return cache.get(request);
} catch (ExecutionException ex) {
@@ -39,10 +39,10 @@ import org.openide.util.ImageUtilities;
/**
* Loads a thumbnail for the given request. Thumbnail candidates are JPEG files
* that are either TSK_WEB_DOWNLOAD or TSK_WEB_CACHE artifacts. JPEG files are
* sorted by most recent if sourced from TSK_WEB_DOWNLOADs. JPEG files are
* sorted by size if sourced from TSK_WEB_CACHE artifacts. Artifacts are first
* loaded from the DomainSearchArtifactsCache and then further analyzed.
* that have either TSK_WEB_DOWNLOAD or TSK_WEB_CACHE artifacts that match the
* domain name (see the DomainSearch getArtifacts() API). JPEG files are sorted
* by most recent if sourced from TSK_WEB_DOWNLOADs and by size if sourced from
* TSK_WEB_CACHE artifacts. The first suitable thumbnail is selected.
*/
public class DomainSearchThumbnailLoader extends CacheLoader<DomainSearchThumbnailRequest, Image> {
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

@@ -183,6 +183,7 @@ public class HEICProcessor implements PictureProcessor {
final Path outputFile = moduleOutputFolder.resolve(baseFileName + ".jpg");
final Path imageMagickErrorOutput = moduleOutputFolder.resolve(IMAGE_MAGICK_ERROR_FILE);
Files.deleteIfExists(imageMagickErrorOutput);
Files.createFile(imageMagickErrorOutput);
// ImageMagick will write the primary image to the output file.
@@ -379,7 +379,10 @@ public class HTMLReport implements TableReportModule {
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/images/validationFailed.png"); //NON-NLS
break;
case TSK_WEB_ACCOUNT_TYPE:
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/images/web-account-type.png.png"); //NON-NLS
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/images/web-account-type.png"); //NON-NLS
break;
case TSK_WEB_FORM_ADDRESS:
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/images/web-form-address.png"); //NON-NLS
break;
default:
logger.log(Level.WARNING, "useDataTypeIcon: unhandled artifact type = {0}", dataType); //NON-NLS
@@ -83,6 +83,7 @@ public class PortableCaseReportModuleSettings implements ReportModuleSettings {
this.chunkSize = ChunkSize.NONE;
this.allTagsSelected = true;
this.allSetsSelected = true;
this.shouldIncludeApplication = false;
}
PortableCaseReportModuleSettings(List<String> setNames, List<TagName> tagNames,
@@ -93,6 +94,7 @@ public class PortableCaseReportModuleSettings implements ReportModuleSettings {
this.chunkSize = chunkSize;
this.allTagsSelected = allTagsSelected;
this.allSetsSelected = allSetsSelected;
this.shouldIncludeApplication = false;
}
@Override
@@ -33,8 +33,8 @@ import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import static org.mockito.Mockito.*;
import org.sleuthkit.autopsy.testutils.TskMockUtils;
import static org.mockito.Mockito.*;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
import org.sleuthkit.datamodel.BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE;
@@ -70,7 +70,7 @@ public class GetArtifactsTest {
*
* @throws TskCoreException
*/
private final void test(BlackboardArtifact.Type artifactType, DataSource dataSource, BlackboardAttribute.Type attributeType,
private void test(BlackboardArtifact.Type artifactType, DataSource dataSource, BlackboardAttribute.Type attributeType,
SortOrder sortOrder, int count, List<BlackboardArtifact> returnArr, TskCoreException blackboardEx,
List<BlackboardArtifact> expectedArr, Class<? extends Exception> expectedException) throws TskCoreException {
@@ -0,0 +1,189 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* 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 org.sleuthkit.autopsy.discovery.search;
import com.google.common.collect.Lists;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
public class DomainSearchArtifactsCacheTest {
private static final ARTIFACT_TYPE WEB_ARTIFACT_TYPE = ARTIFACT_TYPE.TSK_WEB_BOOKMARK;
private static final BlackboardAttribute.Type TSK_DOMAIN = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DOMAIN);
private static final BlackboardAttribute.Type TSK_URL = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL);
@Test(expected = IllegalArgumentException.class)
public void get_NonWebArtifactType_ShouldThrow() throws DiscoveryException {
DomainSearchArtifactsRequest request = new DomainSearchArtifactsRequest(null, "google.com", ARTIFACT_TYPE.TSK_CALLLOG);
DomainSearchArtifactsCache cache = new DomainSearchArtifactsCache();
cache.get(request);
}
/*
* This test is important for ensuring artifact loading can
* be cancelled, which is necessary for a responsive UI.
*/
@Test
public void get_ThreadInterrupted_ShouldThrow() throws TskCoreException {
SleuthkitCase mockCase = mock(SleuthkitCase.class);
BlackboardArtifact mockArtifact = mock(BlackboardArtifact.class);
when(mockCase.getBlackboardArtifacts(WEB_ARTIFACT_TYPE)).thenReturn(Lists.newArrayList(mockArtifact));
DomainSearchArtifactsRequest request = new DomainSearchArtifactsRequest(mockCase, "facebook.com", WEB_ARTIFACT_TYPE);
DomainSearchArtifactsCache cache = new DomainSearchArtifactsCache();
Thread.currentThread().interrupt();
try {
cache.get(request);
// Clear the interrupt flag on failure.
Thread.interrupted();
Assert.fail("Should have thrown a discovery exception.");
} catch (DiscoveryException ex) {
// Clear the interrupt flag on success (or failure).
Thread.interrupted();
Assert.assertEquals(InterruptedException.class, ex.getCause().getCause().getClass());
}
}
@Test
public void get_MatchingDomain_ShouldHaveSizeOne() throws TskCoreException, DiscoveryException {
SleuthkitCase mockCase = mock(SleuthkitCase.class);
BlackboardArtifact mockArtifact = mock(BlackboardArtifact.class);
when(mockArtifact.getAttribute(TSK_DOMAIN)).thenReturn(mockDomainAttribute("google.com"));
when(mockCase.getBlackboardArtifacts(WEB_ARTIFACT_TYPE)).thenReturn(Lists.newArrayList(mockArtifact));
DomainSearchArtifactsRequest request = new DomainSearchArtifactsRequest(mockCase, "google.com", WEB_ARTIFACT_TYPE);
DomainSearchArtifactsCache cache = new DomainSearchArtifactsCache();
List<BlackboardArtifact> artifacts = cache.get(request);
Assert.assertEquals(1, artifacts.size());
Assert.assertEquals(mockArtifact, artifacts.get(0));
}
@Test
public void get_MatchingUrl_ShouldHaveSizeOne() throws TskCoreException, DiscoveryException {
SleuthkitCase mockCase = mock(SleuthkitCase.class);
BlackboardArtifact mockArtifact = mock(BlackboardArtifact.class);
when(mockArtifact.getAttribute(TSK_URL)).thenReturn(mockURLAttribute("https://www.abc.com/search"));
when(mockCase.getBlackboardArtifacts(WEB_ARTIFACT_TYPE)).thenReturn(Lists.newArrayList(mockArtifact));
DomainSearchArtifactsRequest request = new DomainSearchArtifactsRequest(mockCase, "abc.com", WEB_ARTIFACT_TYPE);
DomainSearchArtifactsCache cache = new DomainSearchArtifactsCache();
List<BlackboardArtifact> artifacts = cache.get(request);
Assert.assertEquals(1, artifacts.size());
Assert.assertEquals(mockArtifact, artifacts.get(0));
}
@Test
public void get_MismatchedDomainName_ShouldBeEmpty() throws TskCoreException, DiscoveryException {
SleuthkitCase mockCase = mock(SleuthkitCase.class);
BlackboardArtifact mockArtifact = mock(BlackboardArtifact.class);
when(mockArtifact.getAttribute(TSK_DOMAIN)).thenReturn(mockDomainAttribute("google.com"));
when(mockCase.getBlackboardArtifacts(WEB_ARTIFACT_TYPE)).thenReturn(Lists.newArrayList(mockArtifact));
DomainSearchArtifactsRequest request = new DomainSearchArtifactsRequest(mockCase, "facebook.com", WEB_ARTIFACT_TYPE);
DomainSearchArtifactsCache cache = new DomainSearchArtifactsCache();
List<BlackboardArtifact> artifacts = cache.get(request);
Assert.assertEquals(0, artifacts.size());
}
@Test
public void get_MismatchedUrl_ShouldBeEmpty() throws DiscoveryException, TskCoreException {
SleuthkitCase mockCase = mock(SleuthkitCase.class);
BlackboardArtifact mockArtifact = mock(BlackboardArtifact.class);
when(mockArtifact.getAttribute(TSK_URL)).thenReturn(mockURLAttribute("https://www.dce1.com/search"));
when(mockCase.getBlackboardArtifacts(WEB_ARTIFACT_TYPE)).thenReturn(Lists.newArrayList(mockArtifact));
DomainSearchArtifactsRequest request = new DomainSearchArtifactsRequest(mockCase, "dce.com", WEB_ARTIFACT_TYPE);
DomainSearchArtifactsCache cache = new DomainSearchArtifactsCache();
List<BlackboardArtifact> artifacts = cache.get(request);
Assert.assertEquals(0, artifacts.size());
}
@Test
public void get_CaseInsensitiveDomainAttribute_ShouldHaveSizeOne() throws TskCoreException, DiscoveryException {
SleuthkitCase mockCase = mock(SleuthkitCase.class);
BlackboardArtifact mockArtifact = mock(BlackboardArtifact.class);
when(mockArtifact.getAttribute(TSK_DOMAIN)).thenReturn(mockDomainAttribute("xYZ.coM"));
when(mockCase.getBlackboardArtifacts(WEB_ARTIFACT_TYPE)).thenReturn(Lists.newArrayList(mockArtifact));
DomainSearchArtifactsRequest request = new DomainSearchArtifactsRequest(mockCase, "xyz.com", WEB_ARTIFACT_TYPE);
DomainSearchArtifactsCache cache = new DomainSearchArtifactsCache();
List<BlackboardArtifact> artifacts = cache.get(request);
Assert.assertEquals(1, artifacts.size());
Assert.assertEquals(mockArtifact, artifacts.get(0));
}
@Test
public void get_CaseInsensitiveRequestDomain_ShouldHaveSizeOne() throws TskCoreException, DiscoveryException {
SleuthkitCase mockCase = mock(SleuthkitCase.class);
BlackboardArtifact mockArtifact = mock(BlackboardArtifact.class);
when(mockArtifact.getAttribute(TSK_DOMAIN)).thenReturn(mockDomainAttribute("google.com"));
when(mockCase.getBlackboardArtifacts(WEB_ARTIFACT_TYPE)).thenReturn(Lists.newArrayList(mockArtifact));
DomainSearchArtifactsRequest request = new DomainSearchArtifactsRequest(mockCase, "GooGle.coM", WEB_ARTIFACT_TYPE);
DomainSearchArtifactsCache cache = new DomainSearchArtifactsCache();
List<BlackboardArtifact> artifacts = cache.get(request);
Assert.assertEquals(1, artifacts.size());
Assert.assertEquals(mockArtifact, artifacts.get(0));
}
@Test
public void get_CaseInsensitiveUrlAttribute_ShouldHaveSizeOne() throws TskCoreException, DiscoveryException {
SleuthkitCase mockCase = mock(SleuthkitCase.class);
BlackboardArtifact mockArtifact = mock(BlackboardArtifact.class);
when(mockArtifact.getAttribute(TSK_URL)).thenReturn(mockURLAttribute("https://www.JfK.coM/search"));
when(mockCase.getBlackboardArtifacts(WEB_ARTIFACT_TYPE)).thenReturn(Lists.newArrayList(mockArtifact));
DomainSearchArtifactsRequest request = new DomainSearchArtifactsRequest(mockCase, "jfk.com", WEB_ARTIFACT_TYPE);
DomainSearchArtifactsCache cache = new DomainSearchArtifactsCache();
List<BlackboardArtifact> artifacts = cache.get(request);
Assert.assertEquals(1, artifacts.size());
Assert.assertEquals(mockArtifact, artifacts.get(0));
}
@Test
public void get_CaseInsensitiveRequestUrl_ShouldHaveSizeOne() throws TskCoreException, DiscoveryException {
SleuthkitCase mockCase = mock(SleuthkitCase.class);
BlackboardArtifact mockArtifact = mock(BlackboardArtifact.class);
when(mockArtifact.getAttribute(TSK_URL)).thenReturn(mockURLAttribute("https://www.hop.com/search"));
when(mockCase.getBlackboardArtifacts(WEB_ARTIFACT_TYPE)).thenReturn(Lists.newArrayList(mockArtifact));
DomainSearchArtifactsRequest request = new DomainSearchArtifactsRequest(mockCase, "HoP.cOm", WEB_ARTIFACT_TYPE);
DomainSearchArtifactsCache cache = new DomainSearchArtifactsCache();
List<BlackboardArtifact> artifacts = cache.get(request);
Assert.assertEquals(1, artifacts.size());
Assert.assertEquals(mockArtifact, artifacts.get(0));
}
private BlackboardAttribute mockDomainAttribute(String value) {
return new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, "", value);
}
private BlackboardAttribute mockURLAttribute(String value) {
return new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL, "", value);
}
}
@@ -48,7 +48,7 @@ public class DomainSearchTest {
};
when(cache.get(null, new ArrayList<>(), null, null, null, null, null)).thenReturn(dummyData);
DomainSearch domainSearch = new DomainSearch(cache, null);
DomainSearch domainSearch = new DomainSearch(cache, null, null);
Map<GroupKey, Integer> sizes = domainSearch.getGroupSizes(null,
new ArrayList<>(), null, null, null, null, null);
assertEquals(4, sizes.get(groupOne).longValue());
@@ -83,7 +83,7 @@ public class DomainSearchTest {
when(cache.get(null, new ArrayList<>(), null, null, null, null, null)).thenReturn(dummyData);
DomainSearch domainSearch = new DomainSearch(cache, null);
DomainSearch domainSearch = new DomainSearch(cache, null, null);
Map<GroupKey, Integer> sizes = domainSearch.getGroupSizes(null,
new ArrayList<>(), null, null, null, null, null);
assertEquals(4, sizes.get(groupOne).longValue());
@@ -97,7 +97,7 @@ public class DomainSearchTest {
when(cache.get(null, new ArrayList<>(), null, null, null, null, null)).thenReturn(new HashMap<>());
DomainSearch domainSearch = new DomainSearch(cache, null);
DomainSearch domainSearch = new DomainSearch(cache, null, null);
Map<GroupKey, Integer> sizes = domainSearch.getGroupSizes(null,
new ArrayList<>(), null, null, null, null, null);
assertEquals(0, sizes.size());
@@ -122,7 +122,7 @@ public class DomainSearchTest {
when(cache.get(null, new ArrayList<>(), null, null, null, null, null)).thenReturn(dummyData);
DomainSearch domainSearch = new DomainSearch(cache, null);
DomainSearch domainSearch = new DomainSearch(cache, null, null);
List<Result> firstPage = domainSearch.getDomainsInGroup(null,
new ArrayList<>(), null, null, null, groupOne, 0, 3, null, null);
assertEquals(3, firstPage.size());
@@ -150,7 +150,7 @@ public class DomainSearchTest {
when(cache.get(null, new ArrayList<>(), null, null, null, null, null)).thenReturn(dummyData);
DomainSearch domainSearch = new DomainSearch(cache, null);
DomainSearch domainSearch = new DomainSearch(cache, null, null);
List<Result> firstPage = domainSearch.getDomainsInGroup(null,
new ArrayList<>(), null, null, null, groupOne, 0, 100, null, null);
assertEquals(4, firstPage.size());
@@ -178,7 +178,7 @@ public class DomainSearchTest {
when(cache.get(null, new ArrayList<>(), null, null, null, null, null)).thenReturn(dummyData);
DomainSearch domainSearch = new DomainSearch(cache, null);
DomainSearch domainSearch = new DomainSearch(cache, null, null);
List<Result> firstPage = domainSearch.getDomainsInGroup(null,
new ArrayList<>(), null, null, null, groupOne, 0, 2, null, null);
assertEquals(2, firstPage.size());
@@ -206,7 +206,7 @@ public class DomainSearchTest {
when(cache.get(null, new ArrayList<>(), null, null, null, null, null)).thenReturn(dummyData);
DomainSearch domainSearch = new DomainSearch(cache, null);
DomainSearch domainSearch = new DomainSearch(cache, null, null);
List<Result> firstPage = domainSearch.getDomainsInGroup(null,
new ArrayList<>(), null, null, null, groupOne, 3, 1, null, null);
assertEquals(1, firstPage.size());
@@ -232,7 +232,7 @@ public class DomainSearchTest {
when(cache.get(null, new ArrayList<>(), null, null, null, null, null)).thenReturn(dummyData);
DomainSearch domainSearch = new DomainSearch(cache, null);
DomainSearch domainSearch = new DomainSearch(cache, null, null);
List<Result> firstPage = domainSearch.getDomainsInGroup(null,
new ArrayList<>(), null, null, null, groupOne, 20, 5, null, null);
assertEquals(0, firstPage.size());
@@ -257,7 +257,7 @@ public class DomainSearchTest {
when(cache.get(null, new ArrayList<>(), null, null, null, null, null)).thenReturn(dummyData);
DomainSearch domainSearch = new DomainSearch(cache, null);
DomainSearch domainSearch = new DomainSearch(cache, null, null);
List<Result> firstPage = domainSearch.getDomainsInGroup(null,
new ArrayList<>(), null, null, null, groupOne, 0, 0, null, null);
assertEquals(0, firstPage.size());
@@ -292,7 +292,7 @@ public class DomainSearchTest {
when(cache.get(null, new ArrayList<>(), null, null, null, null, null)).thenReturn(dummyData);
DomainSearch domainSearch = new DomainSearch(cache, null);
DomainSearch domainSearch = new DomainSearch(cache, null, null);
List<Result> firstPage = domainSearch.getDomainsInGroup(null,
new ArrayList<>(), null, null, null, groupOne, 0, 3, null, null);
assertEquals(3, firstPage.size());
@@ -327,7 +327,7 @@ public class DomainSearchTest {
when(cache.get(null, new ArrayList<>(), null, null, null, null, null)).thenReturn(dummyData);
DomainSearch domainSearch = new DomainSearch(cache, null);
DomainSearch domainSearch = new DomainSearch(cache, null, null);
List<Result> firstPage = domainSearch.getDomainsInGroup(null,
new ArrayList<>(), null, null, null, groupTwo, 1, 2, null, null);
assertEquals(2, firstPage.size());
@@ -359,7 +359,7 @@ public class DomainSearchTest {
when(cache.get(null, new ArrayList<>(), null, null, null, null, null)).thenReturn(dummyData);
DomainSearch domainSearch = new DomainSearch(cache, null);
DomainSearch domainSearch = new DomainSearch(cache, null, null);
int start = 0;
int size = 2;
@@ -133,4 +133,7 @@ public class TskMockUtils {
doNothing().when(logger.log(any(Level.class), any(Throwable.class)));
return logger;
}
private TskMockUtils() {
}
}