Merge branch '5370-AddFileSearchCaching' of https://github.com/wschaeferB/autopsy into 5369-DedupingCodeChanges

This commit is contained in:
William Schaefer 2019-08-13 16:06:03 -04:00
commit e1fb17040c
5 changed files with 111 additions and 88 deletions

View File

@ -158,7 +158,7 @@ ResultsPanel.currentPage.displayValue=Page: {0} of {1}
ResultsPanel.currentPageLabel.text=Page: - ResultsPanel.currentPageLabel.text=Page: -
# {0} - selectedPage # {0} - selectedPage
# {1} - maxPage # {1} - maxPage
ResultsPanel.invalidPageNumber.message=The selected page number {0} does not exist. Please select a value of at least 1 and at most {1} ResultsPanel.invalidPageNumber.message=The selected page number {0} does not exist. Please select a value from 1 to {1}.
ResultsPanel.invalidPageNumber.title=Invalid Page Number ResultsPanel.invalidPageNumber.title=Invalid Page Number
ResultsPanel.pageControlsLabel.text=Pages: ResultsPanel.pageControlsLabel.text=Pages:
ResultsPanel.gotoPageLabel.text=Go to Page: ResultsPanel.gotoPageLabel.text=Go to Page:

View File

@ -201,6 +201,13 @@ final class DiscoveryEvents {
} }
} }
static final class NoResultsEvent {
NoResultsEvent(){
//no arg conustructor
}
}
/** /**
* Event to signal that a group has been selected. * Event to signal that a group has been selected.
*/ */

View File

@ -29,9 +29,9 @@ import org.sleuthkit.autopsy.datamodel.utils.FileTypeUtils;
* Utility enums for FileSearch * Utility enums for FileSearch
*/ */
class FileSearchData { class FileSearchData {
private final static long BYTES_PER_MB = 1000000; private final static long BYTES_PER_MB = 1000000;
/** /**
* Enum representing how often the file occurs in the Central Repository. * Enum representing how often the file occurs in the Central Repository.
*/ */
@ -43,43 +43,42 @@ class FileSearchData {
"FileSearchData.Frequency.count_50.displayName=21 - 50", "FileSearchData.Frequency.count_50.displayName=21 - 50",
"FileSearchData.Frequency.count_100.displayName=51 - 100", "FileSearchData.Frequency.count_100.displayName=51 - 100",
"FileSearchData.Frequency.common.displayName=Common", "FileSearchData.Frequency.common.displayName=Common",
"FileSearchData.Frequency.unknown.displayName=Unknown", "FileSearchData.Frequency.unknown.displayName=Unknown",})
})
enum Frequency { enum Frequency {
UNIQUE(0, 1, Bundle.FileSearchData_Frequency_unique_displayName()), UNIQUE(0, 1, Bundle.FileSearchData_Frequency_unique_displayName()),
RARE(1, 5, Bundle.FileSearchData_Frequency_rare_displayName()), RARE(1, 5, Bundle.FileSearchData_Frequency_rare_displayName()),
COUNT_10(2, 10, Bundle.FileSearchData_Frequency_count_10_displayName()), COUNT_10(2, 10, Bundle.FileSearchData_Frequency_count_10_displayName()),
COUNT_20(3, 20, Bundle.FileSearchData_Frequency_count_20_displayName()), COUNT_20(3, 20, Bundle.FileSearchData_Frequency_count_20_displayName()),
COUNT_50(4, 50, Bundle.FileSearchData_Frequency_count_50_displayName()), COUNT_50(4, 50, Bundle.FileSearchData_Frequency_count_50_displayName()),
COUNT_100(5, 100, Bundle.FileSearchData_Frequency_count_100_displayName()), COUNT_100(5, 100, Bundle.FileSearchData_Frequency_count_100_displayName()),
COMMON(6, 0, Bundle.FileSearchData_Frequency_common_displayName()), COMMON(6, 0, Bundle.FileSearchData_Frequency_common_displayName()),
UNKNOWN(7, 0, Bundle.FileSearchData_Frequency_unknown_displayName()); UNKNOWN(7, 0, Bundle.FileSearchData_Frequency_unknown_displayName());
private final int ranking; private final int ranking;
private final String displayName; private final String displayName;
private final int maxOccur; private final int maxOccur;
Frequency(int ranking, int maxOccur, String displayName) { Frequency(int ranking, int maxOccur, String displayName) {
this.ranking = ranking; this.ranking = ranking;
this.maxOccur = maxOccur; this.maxOccur = maxOccur;
this.displayName = displayName; this.displayName = displayName;
} }
/** /**
* Get the rank for sorting. * Get the rank for sorting.
* *
* @return the rank (lower should be displayed first) * @return the rank (lower should be displayed first)
*/ */
int getRanking() { int getRanking() {
return ranking; return ranking;
} }
/** /**
* Get the enum matching the given occurrence count. * Get the enum matching the given occurrence count.
* *
* @param count Number of times a file is in the Central Repository. * @param count Number of times a file is in the Central Repository.
* *
* @return the corresponding enum * @return the corresponding enum
*/ */
static Frequency fromCount(long count) { static Frequency fromCount(long count) {
if (count <= UNIQUE.maxOccur) { if (count <= UNIQUE.maxOccur) {
@ -97,16 +96,16 @@ class FileSearchData {
} }
return COMMON; return COMMON;
} }
/** /**
* Get the list of enums that are valid for filtering. * Get the list of enums that are valid for filtering.
* *
* @return enums that can be used to filter * @return enums that can be used to filter
*/ */
static List<Frequency> getOptionsForFiltering() { static List<Frequency> getOptionsForFiltering() {
return Arrays.asList(UNIQUE, RARE, COUNT_10, COUNT_20, COUNT_50, COUNT_100, COMMON); return Arrays.asList(UNIQUE, RARE, COUNT_10, COUNT_20, COUNT_50, COUNT_100, COMMON);
} }
@Override @Override
public String toString() { public String toString() {
return displayName; return displayName;
@ -122,39 +121,38 @@ class FileSearchData {
"FileSearchData.FileSize.OVER_50MB.displayName=50 - 200 MB", "FileSearchData.FileSize.OVER_50MB.displayName=50 - 200 MB",
"FileSearchData.FileSize.OVER_1MB.displayName=1 - 50 MB", "FileSearchData.FileSize.OVER_1MB.displayName=1 - 50 MB",
"FileSearchData.FileSize.OVER_100KB.displayName=100 KB - 1 MB", "FileSearchData.FileSize.OVER_100KB.displayName=100 KB - 1 MB",
"FileSearchData.FileSize.UNDER_100KB.displayName=Under 100 KB", "FileSearchData.FileSize.UNDER_100KB.displayName=Under 100 KB",})
})
enum FileSize { enum FileSize {
OVER_1GB(0, 1000 * BYTES_PER_MB, -1, Bundle.FileSearchData_FileSize_OVER_1GB_displayName()), OVER_1GB(0, 1000 * BYTES_PER_MB, -1, Bundle.FileSearchData_FileSize_OVER_1GB_displayName()),
OVER_200MB(1, 200 * BYTES_PER_MB, 1000, Bundle.FileSearchData_FileSize_OVER_200MB_displayName()), OVER_200MB(1, 200 * BYTES_PER_MB, 1000 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_OVER_200MB_displayName()),
OVER_50MB(2, 50 * BYTES_PER_MB, 200, Bundle.FileSearchData_FileSize_OVER_50MB_displayName()), OVER_50MB(2, 50 * BYTES_PER_MB, 200 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_OVER_50MB_displayName()),
OVER_1MB(3, 1 * BYTES_PER_MB, 50, Bundle.FileSearchData_FileSize_OVER_1MB_displayName()), OVER_1MB(3, 1 * BYTES_PER_MB, 50 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_OVER_1MB_displayName()),
OVER_100KB(4, 1000, 1 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_OVER_100KB_displayName()), OVER_100KB(4, 100000, 1 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_OVER_100KB_displayName()),
UNDER_100KB(5, 0, 1000, Bundle.FileSearchData_FileSize_UNDER_100KB_displayName()); UNDER_100KB(5, 0, 100000, Bundle.FileSearchData_FileSize_UNDER_100KB_displayName());
private final int ranking; // Must be unique for each value private final int ranking; // Must be unique for each value
private final long minBytes; // Note that the size must be strictly greater than this to match private final long minBytes; // Note that the size must be strictly greater than this to match
private final long maxBytes; private final long maxBytes;
private final String displayName; private final String displayName;
final static long NO_MAXIMUM = -1; final static long NO_MAXIMUM = -1;
FileSize(int ranking, long minMB, long maxMB, String displayName) { FileSize(int ranking, long minB, long maxB, String displayName) {
this.ranking = ranking; this.ranking = ranking;
this.minBytes = minMB; this.minBytes = minB;
if (maxMB >= 0) { if (maxB >= 0) {
this.maxBytes = maxMB; this.maxBytes = maxB;
} else { } else {
this.maxBytes = NO_MAXIMUM; this.maxBytes = NO_MAXIMUM;
} }
this.displayName = displayName; this.displayName = displayName;
} }
/** /**
* Get the enum corresponding to the given file size. * Get the enum corresponding to the given file size. The file size must
* The file size must be strictly greater than minBytes. * be strictly greater than minBytes.
* *
* @param size the file size * @param size the file size
* *
* @return the enum whose range contains the file size * @return the enum whose range contains the file size
*/ */
static FileSize fromSize(long size) { static FileSize fromSize(long size) {
@ -172,45 +170,45 @@ class FileSearchData {
return UNDER_100KB; return UNDER_100KB;
} }
} }
/** /**
* Get the upper limit of the range. * Get the upper limit of the range.
* *
* @return the maximum file size that will fit in this range. * @return the maximum file size that will fit in this range.
*/ */
long getMaxBytes() { long getMaxBytes() {
return maxBytes; return maxBytes;
} }
/** /**
* Get the lower limit of the range. * Get the lower limit of the range.
* *
* @return the maximum file size that is not part of this range * @return the maximum file size that is not part of this range
*/ */
long getMinBytes() { long getMinBytes() {
return minBytes; return minBytes;
} }
/** /**
* Get the rank for sorting. * Get the rank for sorting.
* *
* @return the rank (lower should be displayed first) * @return the rank (lower should be displayed first)
*/ */
int getRanking() { int getRanking() {
return ranking; return ranking;
} }
@Override @Override
public String toString() { public String toString() {
return displayName; return displayName;
} }
} }
/** /**
* Enum representing the file type. * Enum representing the file type. We don't simply use
* We don't simply use FileTypeUtils.FileTypeCategory because: * FileTypeUtils.FileTypeCategory because: - Some file types categories
* - Some file types categories overlap * overlap - It is convenient to have the "OTHER" option for files that
* - It is convenient to have the "OTHER" option for files that don't match the given types * don't match the given types
*/ */
@NbBundle.Messages({ @NbBundle.Messages({
"FileSearchData.FileType.Audio.displayName=Audio", "FileSearchData.FileType.Audio.displayName=Audio",
@ -220,52 +218,52 @@ class FileSearchData {
"FileSearchData.FileType.Executables.displayName=Executables", "FileSearchData.FileType.Executables.displayName=Executables",
"FileSearchData.FileType.Other.displayName=Other/Unknown"}) "FileSearchData.FileType.Other.displayName=Other/Unknown"})
enum FileType { enum FileType {
IMAGE(0, Bundle.FileSearchData_FileType_Image_displayName(), FileTypeUtils.FileTypeCategory.IMAGE.getMediaTypes()), IMAGE(0, Bundle.FileSearchData_FileType_Image_displayName(), FileTypeUtils.FileTypeCategory.IMAGE.getMediaTypes()),
AUDIO(1, Bundle.FileSearchData_FileType_Audio_displayName(), FileTypeUtils.FileTypeCategory.AUDIO.getMediaTypes()), AUDIO(1, Bundle.FileSearchData_FileType_Audio_displayName(), FileTypeUtils.FileTypeCategory.AUDIO.getMediaTypes()),
VIDEO(2, Bundle.FileSearchData_FileType_Video_displayName(), FileTypeUtils.FileTypeCategory.VIDEO.getMediaTypes()), VIDEO(2, Bundle.FileSearchData_FileType_Video_displayName(), FileTypeUtils.FileTypeCategory.VIDEO.getMediaTypes()),
EXECUTABLE(3, Bundle.FileSearchData_FileType_Executables_displayName(), FileTypeUtils.FileTypeCategory.EXECUTABLE.getMediaTypes()), EXECUTABLE(3, Bundle.FileSearchData_FileType_Executables_displayName(), FileTypeUtils.FileTypeCategory.EXECUTABLE.getMediaTypes()),
DOCUMENTS(4, Bundle.FileSearchData_FileType_Documents_displayName(), FileTypeUtils.FileTypeCategory.DOCUMENTS.getMediaTypes()), DOCUMENTS(4, Bundle.FileSearchData_FileType_Documents_displayName(), FileTypeUtils.FileTypeCategory.DOCUMENTS.getMediaTypes()),
OTHER(5, Bundle.FileSearchData_FileType_Other_displayName(), new ArrayList<>()); OTHER(5, Bundle.FileSearchData_FileType_Other_displayName(), new ArrayList<>());
private final int ranking; // For ordering in the UI private final int ranking; // For ordering in the UI
private final String displayName; private final String displayName;
private final Collection<String> mediaTypes; private final Collection<String> mediaTypes;
private FileType (int value, String displayName, Collection<String> mediaTypes) { private FileType(int value, String displayName, Collection<String> mediaTypes) {
this.ranking = value; this.ranking = value;
this.displayName = displayName; this.displayName = displayName;
this.mediaTypes = mediaTypes; this.mediaTypes = mediaTypes;
} }
/** /**
* Get the MIME types matching this category. * Get the MIME types matching this category.
* *
* @return Collection of MIME type strings * @return Collection of MIME type strings
*/ */
Collection<String> getMediaTypes() { Collection<String> getMediaTypes() {
return mediaTypes; return mediaTypes;
} }
@Override @Override
public String toString() { public String toString() {
return displayName; return displayName;
} }
/** /**
* Get the rank for sorting. * Get the rank for sorting.
* *
* @return the rank (lower should be displayed first) * @return the rank (lower should be displayed first)
*/ */
int getRanking() { int getRanking() {
return ranking; return ranking;
} }
/** /**
* Get the enum matching the given MIME type. * Get the enum matching the given MIME type.
* *
* @param mimeType The MIME type for the file * @param mimeType The MIME type for the file
* *
* @return the corresponding enum (will be OTHER if no types matched) * @return the corresponding enum (will be OTHER if no types matched)
*/ */
static FileType fromMIMEtype(String mimeType) { static FileType fromMIMEtype(String mimeType) {
@ -276,41 +274,40 @@ class FileSearchData {
} }
return OTHER; return OTHER;
} }
/** /**
* Get the list of enums that are valid for filtering. * Get the list of enums that are valid for filtering.
* *
* @return enums that can be used to filter * @return enums that can be used to filter
*/ */
static List<FileType> getOptionsForFiltering() { static List<FileType> getOptionsForFiltering() {
return Arrays.asList(IMAGE, AUDIO, VIDEO, EXECUTABLE, DOCUMENTS); return Arrays.asList(IMAGE, AUDIO, VIDEO, EXECUTABLE, DOCUMENTS);
} }
} }
/** /**
* Enum representing the score of the file. * Enum representing the score of the file.
*/ */
@NbBundle.Messages({ @NbBundle.Messages({
"FileSearchData.Score.notable.displayName=Notable", "FileSearchData.Score.notable.displayName=Notable",
"FileSearchData.Score.interesting.displayName=Interesting", "FileSearchData.Score.interesting.displayName=Interesting",
"FileSearchData.Score.unknown.displayName=Unknown", "FileSearchData.Score.unknown.displayName=Unknown",})
})
enum Score { enum Score {
NOTABLE(0, Bundle.FileSearchData_Score_notable_displayName()), NOTABLE(0, Bundle.FileSearchData_Score_notable_displayName()),
INTERESTING(1, Bundle.FileSearchData_Score_interesting_displayName()), INTERESTING(1, Bundle.FileSearchData_Score_interesting_displayName()),
UNKNOWN(2, Bundle.FileSearchData_Score_unknown_displayName()); UNKNOWN(2, Bundle.FileSearchData_Score_unknown_displayName());
private final int ranking; private final int ranking;
private final String displayName; private final String displayName;
Score(int ranking, String displayName) { Score(int ranking, String displayName) {
this.ranking = ranking; this.ranking = ranking;
this.displayName = displayName; this.displayName = displayName;
} }
/** /**
* Get the rank for sorting. * Get the rank for sorting.
* *
* @return the rank (lower should be displayed first) * @return the rank (lower should be displayed first)
*/ */
int getRanking() { int getRanking() {
@ -319,19 +316,19 @@ class FileSearchData {
/** /**
* Get the list of enums that are valid for filtering. * Get the list of enums that are valid for filtering.
* *
* @return enums that can be used to filter * @return enums that can be used to filter
*/ */
static List<Score> getOptionsForFiltering() { static List<Score> getOptionsForFiltering() {
return Arrays.asList(NOTABLE, INTERESTING); return Arrays.asList(NOTABLE, INTERESTING);
} }
@Override @Override
public String toString() { public String toString() {
return displayName; return displayName;
} }
} }
private FileSearchData() { private FileSearchData() {
// Class should not be instantiated // Class should not be instantiated
} }

View File

@ -121,15 +121,19 @@ class GroupListPanel extends javax.swing.JPanel {
*/ */
private void groupSelected(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_groupSelected private void groupSelected(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_groupSelected
if (!evt.getValueIsAdjusting()) { if (!evt.getValueIsAdjusting()) {
String selectedGroup = groupDisplayNameList.getSelectedValue().replaceAll(" \\([0-9]+\\)$", ""); if (groupDisplayNameList.getSelectedValue() != null) {
for (String groupName : groupMap.keySet()) { String selectedGroup = groupDisplayNameList.getSelectedValue().replaceAll(" \\([0-9]+\\)$", "");
if (selectedGroup.equalsIgnoreCase(groupName)) { for (String groupName : groupMap.keySet()) {
selectedGroupName = groupName; if (selectedGroup.equalsIgnoreCase(groupName)) {
DiscoveryEvents.getDiscoveryEventBus().post(new DiscoveryEvents.GroupSelectedEvent( selectedGroupName = groupName;
searchfilters, groupingAttribute, groupSort, fileSortMethod, selectedGroupName, groupMap.get(selectedGroupName), resultType)); DiscoveryEvents.getDiscoveryEventBus().post(new DiscoveryEvents.GroupSelectedEvent(
searchfilters, groupingAttribute, groupSort, fileSortMethod, selectedGroupName, groupMap.get(selectedGroupName), resultType));
break;
}
} }
} else {
DiscoveryEvents.getDiscoveryEventBus().post(new DiscoveryEvents.NoResultsEvent());
} }
} }
}//GEN-LAST:event_groupSelected }//GEN-LAST:event_groupSelected

View File

@ -77,6 +77,7 @@ public class ResultsPanel extends javax.swing.JPanel {
currentPage = pageRetrievedEvent.getPageNumber(); currentPage = pageRetrievedEvent.getPageNumber();
updateControls(); updateControls();
thumbnailViewer.resetComponent(); thumbnailViewer.resetComponent();
tableViewer.resetComponent();
resultsViewerPanel.remove(thumbnailViewer); resultsViewerPanel.remove(thumbnailViewer);
resultsViewerPanel.remove(tableViewer); resultsViewerPanel.remove(tableViewer);
if (pageRetrievedEvent.getType() == FileSearchData.FileType.IMAGE || pageRetrievedEvent.getType() == FileSearchData.FileType.VIDEO) { if (pageRetrievedEvent.getType() == FileSearchData.FileType.IMAGE || pageRetrievedEvent.getType() == FileSearchData.FileType.VIDEO) {
@ -104,7 +105,7 @@ public class ResultsPanel extends javax.swing.JPanel {
* @param groupSelectedEvent The GroupSelectedEvent received. * @param groupSelectedEvent The GroupSelectedEvent received.
*/ */
@Subscribe @Subscribe
void handlePageChangedEvent(DiscoveryEvents.GroupSelectedEvent groupSelectedEvent) { void handleGroupSelectedEvent(DiscoveryEvents.GroupSelectedEvent groupSelectedEvent) {
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
searchFilters = groupSelectedEvent.getFilters(); searchFilters = groupSelectedEvent.getFilters();
groupingAttribute = groupSelectedEvent.getGroupingAttr(); groupingAttribute = groupSelectedEvent.getGroupingAttr();
@ -117,6 +118,20 @@ public class ResultsPanel extends javax.swing.JPanel {
}); });
} }
@Subscribe
void handleNoResultsEvent(DiscoveryEvents.NoResultsEvent noResultsEven) {
SwingUtilities.invokeLater(() -> {
groupSize = 0;
currentPage = 0;
updateControls();
thumbnailViewer.resetComponent();
thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(Node.EMPTY), true));
tableViewer.setNode(new TableFilterNode(new DataResultFilterNode(Node.EMPTY), true));
resultsViewerPanel.revalidate();
resultsViewerPanel.repaint();
});
}
/** /**
* Set the page number and retrieve its contents. * Set the page number and retrieve its contents.
* *
@ -332,7 +347,7 @@ public class ResultsPanel extends javax.swing.JPanel {
*/ */
@Messages({"# {0} - selectedPage", @Messages({"# {0} - selectedPage",
"# {1} - maxPage", "# {1} - maxPage",
"ResultsPanel.invalidPageNumber.message=The selected page number {0} does not exist. Please select a value of at least 1 and at most {1}", "ResultsPanel.invalidPageNumber.message=The selected page number {0} does not exist. Please select a value from 1 to {1}.",
"ResultsPanel.invalidPageNumber.title=Invalid Page Number"}) "ResultsPanel.invalidPageNumber.title=Invalid Page Number"})
private void gotoPageFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gotoPageFieldActionPerformed private void gotoPageFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gotoPageFieldActionPerformed
int newPage; int newPage;