mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
Merged in upstream
This commit is contained in:
commit
fa3c168922
@ -222,7 +222,7 @@ public class DiscoveryAttributes {
|
||||
static class FrequencyAttribute extends AttributeType {
|
||||
|
||||
static final int BATCH_SIZE = 50; // Number of hashes to look up at one time
|
||||
|
||||
|
||||
static final int DOMAIN_BATCH_SIZE = 500; // Number of domains to look up at one time
|
||||
|
||||
@Override
|
||||
@ -255,13 +255,13 @@ public class DiscoveryAttributes {
|
||||
private void processResultFilesForCR(List<Result> results,
|
||||
CentralRepository centralRepoDb) throws DiscoveryException {
|
||||
List<ResultFile> currentFiles = new ArrayList<>();
|
||||
Set<String> hashesToLookUp = new HashSet<>();
|
||||
Set<String> hashesToLookUp = new HashSet<>();
|
||||
List<ResultDomain> domainsToQuery = new ArrayList<>();
|
||||
for (Result result : results) {
|
||||
if (result.getKnown() == TskData.FileKnown.KNOWN) {
|
||||
result.setFrequency(SearchData.Frequency.KNOWN);
|
||||
}
|
||||
|
||||
|
||||
if (result.getType() != SearchData.Type.DOMAIN) {
|
||||
ResultFile file = (ResultFile) result;
|
||||
if (file.getFrequency() == SearchData.Frequency.UNKNOWN
|
||||
@ -270,56 +270,41 @@ public class DiscoveryAttributes {
|
||||
hashesToLookUp.add(file.getFirstInstance().getMd5Hash());
|
||||
currentFiles.add(file);
|
||||
}
|
||||
|
||||
if (hashesToLookUp.size() >= BATCH_SIZE) {
|
||||
computeFrequency(hashesToLookUp, currentFiles, centralRepoDb);
|
||||
|
||||
hashesToLookUp.clear();
|
||||
currentFiles.clear();
|
||||
if (hashesToLookUp.size() >= BATCH_SIZE) {
|
||||
computeFrequency(hashesToLookUp, currentFiles, centralRepoDb);
|
||||
|
||||
hashesToLookUp.clear();
|
||||
currentFiles.clear();
|
||||
}
|
||||
} else {
|
||||
ResultDomain domain = (ResultDomain) result;
|
||||
try {
|
||||
CorrelationAttributeInstance.Type domainAttributeType
|
||||
= centralRepoDb.getCorrelationTypeById(CorrelationAttributeInstance.DOMAIN_TYPE_ID);
|
||||
Long count = centralRepoDb.getCountArtifactInstancesByTypeValue(domainAttributeType, domain.getDomain());
|
||||
domain.setFrequency(SearchData.Frequency.fromCount(count));
|
||||
} catch (CentralRepoException ex) {
|
||||
throw new DiscoveryException("Error encountered querying the central repository.", ex);
|
||||
} catch (CorrelationAttributeNormalizationException ex) {
|
||||
logger.log(Level.INFO, "Domain [%s] could not be normalized for central repository querying, skipping...", domain.getDomain());
|
||||
}
|
||||
}
|
||||
|
||||
if (hashesToLookUp.size() >= BATCH_SIZE) {
|
||||
computeFrequency(hashesToLookUp, currentFiles, centralRepoDb);
|
||||
ResultDomain domainInstance = (ResultDomain) result;
|
||||
domainsToQuery.add(domainInstance);
|
||||
|
||||
|
||||
if (domainsToQuery.size() == DOMAIN_BATCH_SIZE) {
|
||||
queryDomainFrequency(domainsToQuery, centralRepoDb);
|
||||
|
||||
|
||||
domainsToQuery.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
queryDomainFrequency(domainsToQuery, centralRepoDb);
|
||||
computeFrequency(hashesToLookUp, currentFiles, centralRepoDb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void queryDomainFrequency(List<ResultDomain> domainsToQuery, CentralRepository centralRepository) throws DiscoveryException {
|
||||
if (domainsToQuery.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
final Map<String, List<ResultDomain>> resultDomainTable = new HashMap<>();
|
||||
final StringJoiner joiner = new StringJoiner(", ");
|
||||
|
||||
final CorrelationAttributeInstance.Type attributeType = centralRepository.getCorrelationTypeById(CorrelationAttributeInstance.DOMAIN_TYPE_ID);
|
||||
for(ResultDomain domainInstance : domainsToQuery) {
|
||||
for (ResultDomain domainInstance : domainsToQuery) {
|
||||
try {
|
||||
final String domainValue = domainInstance.getDomain();
|
||||
final String normalizedDomain = CorrelationAttributeNormalizer.normalize(attributeType, domainValue);
|
||||
@ -333,10 +318,10 @@ public class DiscoveryAttributes {
|
||||
}
|
||||
|
||||
final String tableName = CentralRepoDbUtil.correlationTypeToInstanceTableName(attributeType);
|
||||
final String domainFrequencyQuery = " value AS domain_name, COUNT(*) AS frequency " +
|
||||
"FROM " + tableName + " " +
|
||||
"WHERE value IN (" + joiner + ") " +
|
||||
"GROUP BY value";
|
||||
final String domainFrequencyQuery = " value AS domain_name, COUNT(*) AS frequency "
|
||||
+ "FROM " + tableName + " "
|
||||
+ "WHERE value IN (" + joiner + ") "
|
||||
+ "GROUP BY value";
|
||||
|
||||
final DomainFrequencyCallback frequencyCallback = new DomainFrequencyCallback(resultDomainTable);
|
||||
centralRepository.processSelectClause(domainFrequencyQuery, frequencyCallback);
|
||||
@ -348,15 +333,15 @@ public class DiscoveryAttributes {
|
||||
throw new DiscoveryException("Fatal exception encountered querying the CR.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class DomainFrequencyCallback implements InstanceTableCallback {
|
||||
|
||||
|
||||
private final Map<String, List<ResultDomain>> domainLookup;
|
||||
private SQLException sqlCause;
|
||||
|
||||
|
||||
private DomainFrequencyCallback(Map<String, List<ResultDomain>> domainLookup) {
|
||||
this.domainLookup = domainLookup;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(ResultSet resultSet) {
|
||||
@ -364,9 +349,9 @@ public class DiscoveryAttributes {
|
||||
while (resultSet.next()) {
|
||||
String domain = resultSet.getString("domain_name");
|
||||
Long frequency = resultSet.getLong("frequency");
|
||||
|
||||
|
||||
List<ResultDomain> domainInstances = domainLookup.get(domain);
|
||||
for(ResultDomain domainInstance : domainInstances) {
|
||||
for (ResultDomain domainInstance : domainInstances) {
|
||||
domainInstance.setFrequency(SearchData.Frequency.fromCount(frequency));
|
||||
}
|
||||
}
|
||||
@ -374,7 +359,7 @@ public class DiscoveryAttributes {
|
||||
this.sqlCause = ex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SQLException getCause() {
|
||||
return this.sqlCause;
|
||||
}
|
||||
@ -742,7 +727,7 @@ public class DiscoveryAttributes {
|
||||
FILE_TAG(new FileTagAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_tag_displayName()),
|
||||
OBJECT_DETECTED(new ObjectDetectedAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_object_displayName()),
|
||||
MOST_RECENT_DATE(new MostRecentActivityDateAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_mostRecentDate_displayName()),
|
||||
FIRST_DATE(new MostRecentActivityDateAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_firstDate_displayName()),
|
||||
FIRST_DATE(new FirstActivityDateAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_firstDate_displayName()),
|
||||
NUMBER_OF_VISITS(new NumberOfVisitsAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_numberOfVisits_displayName()),
|
||||
NO_GROUPING(new NoGroupingAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_none_displayName());
|
||||
|
||||
@ -781,7 +766,7 @@ public class DiscoveryAttributes {
|
||||
return Arrays.asList(FREQUENCY, MOST_RECENT_DATE, FIRST_DATE, NUMBER_OF_VISITS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Computes the CR frequency of all the given hashes and updates the list of
|
||||
* files.
|
||||
|
@ -22,6 +22,7 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
@ -166,7 +167,8 @@ public class DiscoveryKeyUtils {
|
||||
|
||||
/**
|
||||
* Get the fileSorting
|
||||
* @return
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
ResultsSorter.SortingMethod getFileSortingMethod() {
|
||||
return fileSortingMethod;
|
||||
@ -938,6 +940,9 @@ public class DiscoveryKeyUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Key representing a date of most recent activity.
|
||||
*/
|
||||
static class MostRecentActivityDateGroupKey extends GroupKey {
|
||||
|
||||
private final Long epochDate;
|
||||
@ -948,7 +953,7 @@ public class DiscoveryKeyUtils {
|
||||
MostRecentActivityDateGroupKey(Result result) {
|
||||
if (result instanceof ResultDomain) {
|
||||
epochDate = ((ResultDomain) result).getActivityEnd();
|
||||
dateNameString = new SimpleDateFormat("yyyy/MM/dd").format(new Date(TimeUnit.SECONDS.toMillis(epochDate)));
|
||||
dateNameString = new SimpleDateFormat("yyyy/MM/dd", Locale.getDefault()).format(new Date(TimeUnit.SECONDS.toMillis(epochDate)));
|
||||
} else {
|
||||
epochDate = Long.MAX_VALUE;
|
||||
dateNameString = Bundle.DiscoveryKeyUtils_MostRecentActivityDateGroupKey_noDate();
|
||||
@ -1020,6 +1025,9 @@ public class DiscoveryKeyUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Key representing a date of first activity.
|
||||
*/
|
||||
static class FirstActivityDateGroupKey extends GroupKey {
|
||||
|
||||
private final Long epochDate;
|
||||
@ -1030,7 +1038,7 @@ public class DiscoveryKeyUtils {
|
||||
FirstActivityDateGroupKey(Result result) {
|
||||
if (result instanceof ResultDomain) {
|
||||
epochDate = ((ResultDomain) result).getActivityStart();
|
||||
dateNameString = new SimpleDateFormat("yyyy/MM/dd").format(new Date(TimeUnit.SECONDS.toMillis(epochDate)));
|
||||
dateNameString = new SimpleDateFormat("yyyy/MM/dd", Locale.getDefault()).format(new Date(TimeUnit.SECONDS.toMillis(epochDate)));
|
||||
} else {
|
||||
epochDate = Long.MAX_VALUE;
|
||||
dateNameString = Bundle.DiscoveryKeyUtils_FirstActivityDateGroupKey_noDate();
|
||||
|
@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.discovery.search;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@ -33,13 +34,15 @@ import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
public class DomainSearch {
|
||||
|
||||
private final DomainSearchCache searchCache;
|
||||
private final DomainSearchThumbnailCache thumbnailCache;
|
||||
|
||||
public DomainSearch() {
|
||||
this(new DomainSearchCache());
|
||||
this(new DomainSearchCache(), new DomainSearchThumbnailCache());
|
||||
}
|
||||
|
||||
DomainSearch(DomainSearchCache cache) {
|
||||
DomainSearch(DomainSearchCache cache, DomainSearchThumbnailCache thumbnailCache) {
|
||||
this.searchCache = cache;
|
||||
this.thumbnailCache = thumbnailCache;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -123,4 +126,18 @@ public class DomainSearch {
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a thumbnail representation of a domain name. See
|
||||
* DomainSearchThumbnailRequest for more details.
|
||||
*
|
||||
* @param thumbnailRequest Thumbnail request for domain
|
||||
* @return An Image instance or null if no thumbnail is available.
|
||||
*
|
||||
* @throws DiscoveryException If there is an error with Discovery related
|
||||
* processing
|
||||
*/
|
||||
public Image getThumbnail(DomainSearchThumbnailRequest thumbnailRequest) throws DiscoveryException {
|
||||
return thumbnailCache.get(thumbnailRequest);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.cache.CacheBuilder;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
|
||||
/**
|
||||
* Caches artifact requests.
|
||||
*/
|
||||
public class DomainSearchArtifactsCache {
|
||||
|
||||
private static final int MAXIMUM_CACHE_SIZE = 500;
|
||||
private static final LoadingCache<DomainSearchArtifactsRequest, List<BlackboardArtifact>> cache
|
||||
= CacheBuilder.newBuilder()
|
||||
.maximumSize(MAXIMUM_CACHE_SIZE)
|
||||
.build(new DomainSearchArtifactsLoader());
|
||||
|
||||
/**
|
||||
* Get artifact instances that match the requested criteria. If the request
|
||||
* is new, the results will be automatically loaded.
|
||||
*
|
||||
* @param request Artifact request, specifies type, Case, and domain name.
|
||||
* @return A list of matching artifacts
|
||||
*
|
||||
* @throws DiscoveryException Any error that occurs during the loading
|
||||
* process.
|
||||
*/
|
||||
public List<BlackboardArtifact> get(DomainSearchArtifactsRequest request) throws DiscoveryException {
|
||||
try {
|
||||
return cache.get(request);
|
||||
} catch (ExecutionException ex) {
|
||||
throw new DiscoveryException("Error fetching artifacts from cache", ex);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.cache.CacheLoader;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute.Type;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
|
||||
/**
|
||||
* Loads artifacts for the given request. Searches TSK_DOMAIN and TSK_URL
|
||||
* attributes for the requested domain name. TSK_DOMAIN is exact match (ignoring
|
||||
* case). TSK_URL is sub-string match (ignoring case).
|
||||
*/
|
||||
public class DomainSearchArtifactsLoader extends CacheLoader<DomainSearchArtifactsRequest, List<BlackboardArtifact>> {
|
||||
|
||||
private static final Type TSK_DOMAIN = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DOMAIN);
|
||||
private static final Type TSK_URL = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL);
|
||||
|
||||
@Override
|
||||
public List<BlackboardArtifact> load(DomainSearchArtifactsRequest artifactsRequest) throws TskCoreException {
|
||||
final SleuthkitCase caseDb = artifactsRequest.getSleuthkitCase();
|
||||
final String normalizedDomain = artifactsRequest.getDomain().toLowerCase();
|
||||
final List<BlackboardArtifact> artifacts = caseDb.getBlackboardArtifacts(artifactsRequest.getArtifactType());
|
||||
final List<BlackboardArtifact> matchingDomainArtifacts = new ArrayList<>();
|
||||
|
||||
for (BlackboardArtifact artifact : artifacts) {
|
||||
final BlackboardAttribute tskDomain = artifact.getAttribute(TSK_DOMAIN);
|
||||
final BlackboardAttribute tskUrl = artifact.getAttribute(TSK_URL);
|
||||
|
||||
if (tskDomain != null && tskDomain.getValueString().equalsIgnoreCase(normalizedDomain)) {
|
||||
matchingDomainArtifacts.add(artifact);
|
||||
} else if (tskUrl != null && tskUrl.getValueString().toLowerCase().contains(normalizedDomain)) {
|
||||
matchingDomainArtifacts.add(artifact);
|
||||
}
|
||||
}
|
||||
|
||||
return matchingDomainArtifacts;
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 java.util.Objects;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||
|
||||
/**
|
||||
* Requests artifacts of a specific type and domain from a given Case.
|
||||
*/
|
||||
public class DomainSearchArtifactsRequest {
|
||||
|
||||
private final SleuthkitCase sleuthkitCase;
|
||||
private final String domain;
|
||||
private final ARTIFACT_TYPE artifactType;
|
||||
|
||||
public DomainSearchArtifactsRequest(SleuthkitCase sleuthkitCase,
|
||||
String domain, ARTIFACT_TYPE artifactType) {
|
||||
this.sleuthkitCase = sleuthkitCase;
|
||||
this.domain = domain;
|
||||
this.artifactType = artifactType;
|
||||
}
|
||||
|
||||
public SleuthkitCase getSleuthkitCase() {
|
||||
return sleuthkitCase;
|
||||
}
|
||||
|
||||
public String getDomain() {
|
||||
return domain;
|
||||
}
|
||||
|
||||
public ARTIFACT_TYPE getArtifactType() {
|
||||
return artifactType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(other instanceof DomainSearchArtifactsRequest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DomainSearchArtifactsRequest otherRequest = (DomainSearchArtifactsRequest) other;
|
||||
return this.sleuthkitCase == otherRequest.getSleuthkitCase()
|
||||
&& this.domain.equals(otherRequest.getDomain())
|
||||
&& this.artifactType == otherRequest.getArtifactType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 79 * 5 + Objects.hash(this.domain, this.artifactType);
|
||||
}
|
||||
}
|
@ -36,10 +36,10 @@ import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
class DomainSearchCache {
|
||||
|
||||
private static final int MAXIMUM_CACHE_SIZE = 10;
|
||||
private static final LoadingCache<SearchKey, Map<GroupKey, List<Result>>> cache =
|
||||
CacheBuilder.newBuilder()
|
||||
.maximumSize(MAXIMUM_CACHE_SIZE)
|
||||
.build(new DomainSearchCacheLoader());
|
||||
private static final LoadingCache<SearchKey, Map<GroupKey, List<Result>>> cache
|
||||
= CacheBuilder.newBuilder()
|
||||
.maximumSize(MAXIMUM_CACHE_SIZE)
|
||||
.build(new DomainSearchCacheLoader());
|
||||
|
||||
/**
|
||||
* Get domain search results matching the given parameters. If no results
|
||||
@ -57,7 +57,7 @@ class DomainSearchCache {
|
||||
groupSortingType, domainSortingMethod, caseDb, centralRepoDb);
|
||||
|
||||
return cache.get(searchKey);
|
||||
} catch (Throwable ex) {
|
||||
} catch (ExecutionException ex) {
|
||||
throw new DiscoveryException("Error fetching results from cache", ex.getCause());
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.cache.CacheBuilder;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import java.awt.Image;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
/**
|
||||
* Caches thumbnail requests.
|
||||
*/
|
||||
public class DomainSearchThumbnailCache {
|
||||
|
||||
private static final int MAXIMUM_CACHE_SIZE = 500;
|
||||
private static final LoadingCache<DomainSearchThumbnailRequest, Image> cache
|
||||
= CacheBuilder.newBuilder()
|
||||
.maximumSize(MAXIMUM_CACHE_SIZE)
|
||||
.build(new DomainSearchThumbnailLoader());
|
||||
|
||||
/**
|
||||
* Get a thumbnail for the requested domain. If the request is new, the
|
||||
* thumbnail will be automatically loaded.
|
||||
*
|
||||
* @param request Requested domain to thumbnail
|
||||
* @return The thumbnail Image instance, or null if no thumbnail is available
|
||||
*
|
||||
* @throws DiscoveryException If any error occurs during thumbnail generation.
|
||||
*/
|
||||
public Image get(DomainSearchThumbnailRequest request) throws DiscoveryException {
|
||||
try {
|
||||
return cache.get(request);
|
||||
} catch (ExecutionException ex) {
|
||||
throw new DiscoveryException("Error fetching artifacts from cache", ex);
|
||||
}
|
||||
}
|
||||
}
|
149
Core/src/org/sleuthkit/autopsy/discovery/search/DomainSearchThumbnailLoader.java
Executable file
149
Core/src/org/sleuthkit/autopsy/discovery/search/DomainSearchThumbnailLoader.java
Executable file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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.cache.CacheLoader;
|
||||
import java.awt.Image;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
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.
|
||||
*/
|
||||
public class DomainSearchThumbnailLoader extends CacheLoader<DomainSearchThumbnailRequest, Image> {
|
||||
|
||||
private static final String UNSUPPORTED_IMAGE = "org/sleuthkit/autopsy/images/image-extraction-not-supported.png";
|
||||
|
||||
private static final String JPG_EXTENSION = "jpg";
|
||||
private static final String JPG_MIME_TYPE = "image/jpeg";
|
||||
private final DomainSearchArtifactsCache artifactsCache;
|
||||
|
||||
public DomainSearchThumbnailLoader() {
|
||||
this(new DomainSearchArtifactsCache());
|
||||
}
|
||||
|
||||
DomainSearchThumbnailLoader(DomainSearchArtifactsCache artifactsCache) {
|
||||
this.artifactsCache = artifactsCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image load(DomainSearchThumbnailRequest thumbnailRequest) throws TskCoreException, DiscoveryException {
|
||||
|
||||
final SleuthkitCase caseDb = thumbnailRequest.getSleuthkitCase();
|
||||
|
||||
final DomainSearchArtifactsRequest webDownloadsRequest = new DomainSearchArtifactsRequest(
|
||||
caseDb, thumbnailRequest.getDomain(), TSK_WEB_DOWNLOAD);
|
||||
|
||||
final List<BlackboardArtifact> webDownloads = artifactsCache.get(webDownloadsRequest);
|
||||
final List<AbstractFile> webDownloadPictures = getJpegsFromWebDownload(caseDb, webDownloads);
|
||||
Collections.sort(webDownloadPictures, (file1, file2) -> Long.compare(file1.getCrtime(), file2.getCrtime()));
|
||||
|
||||
for (int i = webDownloadPictures.size() - 1; i >= 0; i--) {
|
||||
// Get the most recent image, according to creation time.
|
||||
final AbstractFile mostRecent = webDownloadPictures.get(i);
|
||||
|
||||
final Image candidateThumbnail = ImageUtils.getThumbnail(mostRecent, thumbnailRequest.getIconSize());
|
||||
if (candidateThumbnail != ImageUtils.getDefaultThumbnail()) {
|
||||
return candidateThumbnail;
|
||||
}
|
||||
}
|
||||
|
||||
final DomainSearchArtifactsRequest webCacheRequest = new DomainSearchArtifactsRequest(
|
||||
caseDb, thumbnailRequest.getDomain(), TSK_WEB_CACHE);
|
||||
|
||||
final List<BlackboardArtifact> webCacheArtifacts = artifactsCache.get(webCacheRequest);
|
||||
final List<AbstractFile> webCachePictures = getJpegsFromWebCache(caseDb, webCacheArtifacts);
|
||||
Collections.sort(webCachePictures, (file1, file2) -> Long.compare(file1.getSize(), file2.getSize()));
|
||||
|
||||
for (int i = webCachePictures.size() - 1; i >= 0; i--) {
|
||||
// Get the largest image, according to file size.
|
||||
final AbstractFile largest = webCachePictures.get(i);
|
||||
|
||||
final Image candidateThumbnail = ImageUtils.getThumbnail(largest, thumbnailRequest.getIconSize());
|
||||
if (candidateThumbnail != ImageUtils.getDefaultThumbnail()) {
|
||||
return candidateThumbnail;
|
||||
}
|
||||
}
|
||||
|
||||
return ImageUtilities.loadImage(UNSUPPORTED_IMAGE, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all JPEG source files from TSK_WEB_DOWNLOAD instances.
|
||||
*/
|
||||
private List<AbstractFile> getJpegsFromWebDownload(SleuthkitCase caseDb, List<BlackboardArtifact> artifacts) throws TskCoreException {
|
||||
final List<AbstractFile> jpegs = new ArrayList<>();
|
||||
|
||||
for (BlackboardArtifact artifact : artifacts) {
|
||||
final Content sourceContent = caseDb.getContentById(artifact.getObjectID());
|
||||
addIfJpeg(jpegs, sourceContent);
|
||||
}
|
||||
|
||||
return jpegs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all JPEG source files from TSK_WEB_CACHE instances.
|
||||
*/
|
||||
private List<AbstractFile> getJpegsFromWebCache(SleuthkitCase caseDb, List<BlackboardArtifact> artifacts) throws TskCoreException {
|
||||
final BlackboardAttribute.Type TSK_PATH_ID = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH_ID);
|
||||
|
||||
final List<AbstractFile> jpegs = new ArrayList<>();
|
||||
for (BlackboardArtifact artifact : artifacts) {
|
||||
final BlackboardAttribute tskPathId = artifact.getAttribute(TSK_PATH_ID);
|
||||
if (tskPathId != null) {
|
||||
final Content sourceContent = caseDb.getContentById(tskPathId.getValueLong());
|
||||
addIfJpeg(jpegs, sourceContent);
|
||||
}
|
||||
}
|
||||
|
||||
return jpegs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the candidate source content is indeed a JPEG file.
|
||||
*/
|
||||
private void addIfJpeg(List<AbstractFile> files, Content sourceContent) {
|
||||
if ((sourceContent instanceof AbstractFile) && !(sourceContent instanceof DataSource)) {
|
||||
final AbstractFile file = (AbstractFile) sourceContent;
|
||||
if (JPG_EXTENSION.equals(file.getNameExtension())
|
||||
|| JPG_MIME_TYPE.equals(file.getMIMEType())) {
|
||||
files.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 java.util.Objects;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
|
||||
/**
|
||||
* Requests a thumbnail to be generated for a given Case, domain and
|
||||
* size. IconSize should be a value obtained from ImageUtils.
|
||||
*/
|
||||
public class DomainSearchThumbnailRequest {
|
||||
|
||||
private final SleuthkitCase sleuthkitCase;
|
||||
private final String domain;
|
||||
private final int iconSize;
|
||||
|
||||
public DomainSearchThumbnailRequest(SleuthkitCase sleuthkitCase,
|
||||
String domain, int iconSize) {
|
||||
this.sleuthkitCase = sleuthkitCase;
|
||||
this.domain = domain;
|
||||
this.iconSize = iconSize;
|
||||
}
|
||||
|
||||
public SleuthkitCase getSleuthkitCase() {
|
||||
return sleuthkitCase;
|
||||
}
|
||||
|
||||
public String getDomain() {
|
||||
return domain;
|
||||
}
|
||||
|
||||
public int getIconSize() {
|
||||
return iconSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(other instanceof DomainSearchThumbnailRequest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DomainSearchThumbnailRequest otherRequest = (DomainSearchThumbnailRequest) other;
|
||||
return this.sleuthkitCase == otherRequest.getSleuthkitCase()
|
||||
&& this.domain.equals(otherRequest.getDomain())
|
||||
&& this.iconSize == otherRequest.getIconSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 79 * 5 + Objects.hash(this.domain, this.iconSize);
|
||||
}
|
||||
}
|
@ -25,6 +25,7 @@ import javax.swing.DefaultListModel;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
||||
import org.sleuthkit.autopsy.discovery.search.SearchFiltering.ArtifactTypeFilter;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
@ -133,10 +134,11 @@ class ArtifactTypeFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NbBundle.Messages({"ArtifactTypeFilterPanel.selectionNeeded.text=At least one Result type must be selected."})
|
||||
@Override
|
||||
String checkForError() {
|
||||
if (artifactTypeCheckbox.isSelected() && artifactList.getSelectedValuesList().isEmpty()) {
|
||||
return "At least one Result type must be selected.";
|
||||
return Bundle.ArtifactTypeFilterPanel_selectionNeeded_text();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
ArtifactTypeFilterPanel.selectionNeeded.text=At least one Result type must be selected.
|
||||
CTL_OpenDiscoveryAction=Discovery
|
||||
# {0} - dataSourceName
|
||||
DataSourceModuleWrapper.exifModule.text=Exif Parser module was not run on data source: {0}\n
|
||||
@ -7,6 +8,8 @@ DataSourceModuleWrapper.fileTypeModule.text=File Type Identification module was
|
||||
DataSourceModuleWrapper.hashModule.text=Hash Lookup module was not run on data source: {0}\n
|
||||
# {0} - timeZone
|
||||
DateFilterPanel.dateRange.text=Date Range ({0}):
|
||||
DateFilterPanel.invalidRange.text=Range or Only Last must be selected
|
||||
DateFilterPanel.startOrEndNeeded.text=A start or end date must be specified to use the range filter
|
||||
DiscoveryDialog.name.text=Discovery
|
||||
DiscoveryTopComponent.cancelButton.text=Cancel Search
|
||||
DiscoveryTopComponent.name=\ Discovery
|
||||
|
@ -19,8 +19,8 @@
|
||||
package org.sleuthkit.autopsy.discovery.ui;
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDate;
|
||||
import java.time.Period;
|
||||
import java.time.ZoneId;
|
||||
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
|
||||
import javax.swing.JCheckBox;
|
||||
@ -278,13 +278,15 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
}
|
||||
}
|
||||
|
||||
@NbBundle.Messages({"DateFilterPanel.invalidRange.text=Range or Only Last must be selected",
|
||||
"DateFilterPanel.startOrEndNeeded.text=A start or end date must be specified to use the range filter"})
|
||||
@Override
|
||||
String checkForError() {
|
||||
if (dateFilterCheckBox.isSelected()) {
|
||||
if (!(rangeRadioButton.isSelected() || mostRecentRadioButton.isSelected())) {
|
||||
return "Range or Only Last must be selected";
|
||||
return Bundle.DateFilterPanel_invalidRange_text();
|
||||
} else if (rangeRadioButton.isSelected() && !(startCheckBox.isSelected() || endCheckBox.isSelected())) {
|
||||
return "A start or end date must be specified to use the range filter";
|
||||
return Bundle.DateFilterPanel_startOrEndNeeded_text();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
@ -292,13 +294,12 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
|
||||
@Override
|
||||
AbstractFilter getFilter() {
|
||||
|
||||
if (dateFilterCheckBox.isSelected()) {
|
||||
LocalDate startDate = LocalDate.MIN;
|
||||
LocalDate endDate = LocalDate.MAX;
|
||||
ZoneId zone = Utils.getUserPreferredZoneId();
|
||||
if (rangeRadioButton.isSelected() && (startCheckBox.isSelected() || endCheckBox.isSelected())) {
|
||||
if (startCheckBox.isSelected() && startDatePicker.getDate().equals(startDate)) {
|
||||
if (startCheckBox.isSelected() && startDatePicker.getDate() != null) {
|
||||
startDate = startDatePicker.getDate();
|
||||
}
|
||||
if (endCheckBox.isSelected() && endDatePicker.getDate() != null) {
|
||||
@ -306,7 +307,7 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
}
|
||||
} else if (dateFilterCheckBox.isSelected() && mostRecentRadioButton.isSelected()) {
|
||||
endDate = LocalDate.now();
|
||||
startDate = LocalDate.now().minus(Duration.ofDays((long) daysSpinner.getValue()));
|
||||
startDate = LocalDate.now().minus(Period.ofDays((Integer) daysSpinner.getValue()));
|
||||
}
|
||||
return new SearchFiltering.ArtifactDateRangeFilter(startDate.atStartOfDay(zone).toEpochSecond(), endDate.atStartOfDay(zone).toEpochSecond() + SECS_PER_DAY);//to insure end date is inclusive
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import java.awt.Point;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JList;
|
||||
@ -38,8 +39,7 @@ class DomainSummaryPanel extends javax.swing.JPanel implements ListCellRenderer<
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Color SELECTION_COLOR = new Color(0, 120, 215);
|
||||
private static final int MAX_NAME_STRING = 90;
|
||||
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("MMM dd yyyy");
|
||||
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("MMM dd yyyy", Locale.getDefault());
|
||||
|
||||
/**
|
||||
* Creates new form DomainPanel.
|
||||
|
@ -11,6 +11,7 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||
@ -38,6 +39,8 @@
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<DomainWrapper>"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
|
@ -21,8 +21,7 @@ package org.sleuthkit.autopsy.discovery.ui;
|
||||
import javax.swing.DefaultListModel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author wschaefer
|
||||
* A JPanel to display domain summaries.
|
||||
*/
|
||||
public class DomainSummaryViewer extends javax.swing.JPanel {
|
||||
|
||||
@ -57,7 +56,7 @@ public class DomainSummaryViewer extends javax.swing.JPanel {
|
||||
private void initComponents() {
|
||||
|
||||
domainScrollPane = new javax.swing.JScrollPane();
|
||||
domainList = new javax.swing.JList<>();
|
||||
javax.swing.JList<DomainWrapper> domainList = new javax.swing.JList<>();
|
||||
|
||||
setLayout(new java.awt.BorderLayout());
|
||||
|
||||
@ -70,7 +69,6 @@ public class DomainSummaryViewer extends javax.swing.JPanel {
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JList<DomainWrapper> domainList;
|
||||
private javax.swing.JScrollPane domainScrollPane;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
|
@ -22,12 +22,12 @@ import java.awt.Image;
|
||||
import org.sleuthkit.autopsy.discovery.search.ResultDomain;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author wschaefer
|
||||
* Class to wrap all the information necessary for a domain summary to be
|
||||
* displayed.
|
||||
*/
|
||||
public class DomainWrapper {
|
||||
|
||||
private ResultDomain domain;
|
||||
private final ResultDomain domain;
|
||||
private Image thumbnail = null;
|
||||
|
||||
/**
|
||||
@ -43,10 +43,10 @@ public class DomainWrapper {
|
||||
/**
|
||||
* Set the thumbnail which exists.
|
||||
*
|
||||
* @param thumbnail The Image object which will be used to represent this
|
||||
* @param thumbnail The image object which will be used to represent this
|
||||
* domain object.
|
||||
*/
|
||||
void setThumnail(Image thumbnail) {
|
||||
void setThumbnail(Image thumbnail) {
|
||||
this.thumbnail = thumbnail;
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ public class DomainWrapper {
|
||||
/**
|
||||
* Get the image to be used for the domain.
|
||||
*
|
||||
* @return The Image which represents the domain.
|
||||
* @return The image which represents the domain.
|
||||
*/
|
||||
Image getThumbnail() {
|
||||
return thumbnail;
|
||||
|
@ -120,7 +120,7 @@ final class ResultsPanel extends javax.swing.JPanel {
|
||||
}
|
||||
}
|
||||
});
|
||||
//JIRA-TODO
|
||||
//JIRA-TODO 6307 Add listener for domainSummaryViewer when 6782, 6773, and the other details area related stories are done
|
||||
}
|
||||
|
||||
/**
|
||||
@ -812,7 +812,7 @@ final class ResultsPanel extends javax.swing.JPanel {
|
||||
|
||||
@Override
|
||||
protected Void doInBackground() throws Exception {
|
||||
domainWrapper.setThumnail(null);
|
||||
domainWrapper.setThumbnail(null);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -821,13 +821,13 @@ final class ResultsPanel extends javax.swing.JPanel {
|
||||
try {
|
||||
get();
|
||||
} catch (InterruptedException | ExecutionException ex) {
|
||||
domainWrapper.setThumnail(null);
|
||||
domainWrapper.setThumbnail(null);
|
||||
logger.log(Level.WARNING, "Document Worker Exception", ex);
|
||||
} catch (CancellationException ignored) {
|
||||
domainWrapper.setThumnail(null);
|
||||
domainWrapper.setThumbnail(null);
|
||||
//we want to do nothing in response to this since we allow it to be cancelled
|
||||
}
|
||||
documentPreviewViewer.repaint();
|
||||
domainSummaryViewer.repaint();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
DomainSearch domainSearch = new DomainSearch(cache, 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);
|
||||
DomainSearch domainSearch = new DomainSearch(cache, 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);
|
||||
DomainSearch domainSearch = new DomainSearch(cache, 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);
|
||||
DomainSearch domainSearch = new DomainSearch(cache, 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);
|
||||
DomainSearch domainSearch = new DomainSearch(cache, 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);
|
||||
DomainSearch domainSearch = new DomainSearch(cache, 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);
|
||||
DomainSearch domainSearch = new DomainSearch(cache, 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);
|
||||
DomainSearch domainSearch = new DomainSearch(cache, 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);
|
||||
DomainSearch domainSearch = new DomainSearch(cache, 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);
|
||||
DomainSearch domainSearch = new DomainSearch(cache, 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);
|
||||
DomainSearch domainSearch = new DomainSearch(cache, 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);
|
||||
DomainSearch domainSearch = new DomainSearch(cache, null);
|
||||
|
||||
int start = 0;
|
||||
int size = 2;
|
||||
|
Loading…
x
Reference in New Issue
Block a user