diff --git a/Core/ivy.xml b/Core/ivy.xml
index 4c4bef4f9a..63fdd9ed92 100644
--- a/Core/ivy.xml
+++ b/Core/ivy.xml
@@ -50,9 +50,6 @@
-
-
-
diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml
index f82ab0c7af..61e6a86b04 100644
--- a/Core/nbproject/project.xml
+++ b/Core/nbproject/project.xml
@@ -479,14 +479,6 @@
ext/jxmapviewer2-2.4.jar
release/modules/ext/jxmapviewer2-2.4.jar
-
- ext/jfreechart-1.0.19.jar
- release/modules/ext/jfreechart-1.0.19.jar
-
-
- ext/jcommon-1.0.23.jar
- release/modules/ext/jcommon-1.0.23.jar
-
ext/jdom-2.0.5-contrib.jar
release/modules/ext/jdom-2.0.5-contrib.jar
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java
index 1e05403dd8..59b345501b 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java
@@ -70,7 +70,7 @@ import org.sleuthkit.autopsy.actions.OpenOutputFolderAction;
import org.sleuthkit.autopsy.appservices.AutopsyService;
import org.sleuthkit.autopsy.appservices.AutopsyService.CaseContext;
import org.sleuthkit.autopsy.casemodule.CaseMetadata.CaseMetadataException;
-import org.sleuthkit.autopsy.datasourcesummary.ui.DataSourceSummaryAction;
+import org.sleuthkit.autopsy.casemodule.datasourcesummary.DataSourceSummaryAction;
import org.sleuthkit.autopsy.casemodule.events.AddingDataSourceEvent;
import org.sleuthkit.autopsy.casemodule.events.AddingDataSourceFailedEvent;
import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagAddedEvent;
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties
similarity index 94%
rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties
rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties
index 462d910dde..24a312f733 100644
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties
@@ -33,6 +33,7 @@ DataSourceSummaryDetailsPanel.acquisitionDetailsTextArea.text=
DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text=Acquisition Details:
DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text=Unallocated Space:
DataSourceSummaryDetailsPanel.unallocatedSizeValue.text=
+DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type
DataSourceSummaryCountsPanel.byCategoryLabel.text=Files by Category
-DataSourceSummaryCountsPanel.resultsByTypeLabel.text=Results by Type
+DataSourceSummaryCountsPanel.jLabel1.text=Results by Type
DataSourceSummaryUserActivityPanel.programsRunLabel.text=Top Programs Run
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties-MERGED
similarity index 95%
rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED
rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties-MERGED
index 811040a3ca..ba0d3510c7 100644
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties-MERGED
@@ -1,7 +1,6 @@
CTL_DataSourceSummaryAction=Data Source Summary
DataSourceSummaryCountsPanel.ArtifactCountsTableModel.count.header=Count
DataSourceSummaryCountsPanel.ArtifactCountsTableModel.type.header=Result Type
-DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type
DataSourceSummaryCountsPanel.FilesByCategoryTableModel.all.row=All
DataSourceSummaryCountsPanel.FilesByCategoryTableModel.allocated.row=Allocated
DataSourceSummaryCountsPanel.FilesByCategoryTableModel.count.header=Count
@@ -16,8 +15,6 @@ DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.executables.row=Executabl
DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.images.row=Images
DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.type.header=File Type
DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.videos.row=Videos
-DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_notAnalyzed_label=Not Analyzed
-DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_other_label=Other
DataSourceSummaryDetailsPanel.getDataSources.error.text=Failed to get the list of datasources for the current case.
DataSourceSummaryDetailsPanel.getDataSources.error.title=Load Failure
DataSourceSummaryDetailsPanel.units.bytes=\ bytes
@@ -61,8 +58,9 @@ DataSourceSummaryDetailsPanel.acquisitionDetailsTextArea.text=
DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text=Acquisition Details:
DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text=Unallocated Space:
DataSourceSummaryDetailsPanel.unallocatedSizeValue.text=
+DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type
DataSourceSummaryCountsPanel.byCategoryLabel.text=Files by Category
-DataSourceSummaryCountsPanel.resultsByTypeLabel.text=Results by Type
+DataSourceSummaryCountsPanel.jLabel1.text=Results by Type
DataSourceSummaryDialog.window.title=Data Sources Summary
DataSourceSummaryNode.column.dataSourceName.header=Data Source Name
DataSourceSummaryNode.column.files.header=Files
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle_ja.properties
similarity index 100%
rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle_ja.properties
rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle_ja.properties
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceBrowser.form b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceBrowser.form
similarity index 100%
rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceBrowser.form
rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceBrowser.form
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceBrowser.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceBrowser.java
similarity index 96%
rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceBrowser.java
rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceBrowser.java
index a31bbb03f7..92967738b0 100644
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceBrowser.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceBrowser.java
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.datasourcesummary.ui;
+package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.awt.EventQueue;
import java.beans.PropertyVetoException;
@@ -35,11 +35,10 @@ import javax.swing.event.ListSelectionListener;
import org.openide.nodes.Node;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
-import org.sleuthkit.autopsy.datasourcesummary.ui.DataSourceSummaryNode.DataSourceSummaryEntryNode;
+import org.sleuthkit.autopsy.casemodule.datasourcesummary.DataSourceSummaryNode.DataSourceSummaryEntryNode;
import static javax.swing.SwingConstants.RIGHT;
import javax.swing.SwingUtilities;
import javax.swing.table.TableColumn;
-import org.sleuthkit.autopsy.datasourcesummary.datamodel.CaseDataSourcesSummary;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.IngestJobInfo;
import org.sleuthkit.datamodel.SleuthkitCase;
@@ -153,8 +152,8 @@ final class DataSourceBrowser extends javax.swing.JPanel implements ExplorerMana
private List getDataSourceSummaryList(Map usageMap, Map fileCountsMap) {
List summaryList = new ArrayList<>();
- final Map artifactCountsMap = CaseDataSourcesSummary.getCountsOfArtifacts();
- final Map tagCountsMap = CaseDataSourcesSummary.getCountsOfTags();
+ final Map artifactCountsMap = DataSourceInfoUtilities.getCountsOfArtifacts();
+ final Map tagCountsMap = DataSourceInfoUtilities.getCountsOfTags();
try {
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
for (DataSource dataSource : skCase.getDataSources()) {
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java
new file mode 100644
index 0000000000..7e66e56682
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java
@@ -0,0 +1,819 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2019 - 2020 Basis Technology Corp.
+ * Contact: carrier sleuthkit 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.casemodule.datasourcesummary;
+
+import java.io.File;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import org.sleuthkit.autopsy.coreutils.Logger;
+import org.sleuthkit.datamodel.SleuthkitCase;
+import org.sleuthkit.datamodel.TskCoreException;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import org.apache.commons.lang.StringUtils;
+import org.sleuthkit.autopsy.casemodule.Case;
+import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
+import org.sleuthkit.datamodel.BlackboardArtifact;
+import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
+import org.sleuthkit.datamodel.TskData;
+import org.sleuthkit.datamodel.BlackboardAttribute;
+import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
+import org.sleuthkit.datamodel.DataSource;
+
+/**
+ * Utilities for getting information about a data source or all data sources
+ * from the case database.
+ */
+final class DataSourceInfoUtilities {
+
+ private static final Logger logger = Logger.getLogger(DataSourceInfoUtilities.class.getName());
+
+ /**
+ * Gets a count of files for a particular datasource where it is not a
+ * virtual directory and has a name.
+ *
+ * @param currentDataSource The datasource.
+ * @param additionalWhere Additional sql where clauses.
+ * @param onError The message to log on error.
+ *
+ * @return The count of files or null on error.
+ */
+ private static Long getCountOfFiles(DataSource currentDataSource, String additionalWhere, String onError) {
+ if (currentDataSource != null) {
+ try {
+ SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
+ return skCase.countFilesWhere(
+ "dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
+ + " AND name<>''"
+ + " AND data_source_obj_id=" + currentDataSource.getId()
+ + " AND " + additionalWhere);
+ } catch (TskCoreException | NoCurrentCaseException ex) {
+ logger.log(Level.WARNING, onError, ex);
+ //unable to get count of files for the specified types cell will be displayed as empty
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get count of files in a data source.
+ *
+ * @param currentDataSource The data source.
+ *
+ * @return The count.
+ */
+ static Long getCountOfFiles(DataSource currentDataSource) {
+ return getCountOfFiles(currentDataSource,
+ "type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType(),
+ "Unable to get count of files, providing empty results");
+ }
+
+ /**
+ * Get count of unallocated files in a data source.
+ *
+ * @param currentDataSource The data source.
+ *
+ * @return The count.
+ */
+ static Long getCountOfUnallocatedFiles(DataSource currentDataSource) {
+ return getCountOfFiles(currentDataSource,
+ "type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
+ + " AND dir_flags=" + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue(),
+ "Unable to get counts of unallocated files for datasource, providing empty results");
+ }
+
+ /**
+ * Get count of directories in a data source.
+ *
+ * @param currentDataSource The data source.
+ *
+ * @return The count.
+ */
+ static Long getCountOfDirectories(DataSource currentDataSource) {
+ return getCountOfFiles(currentDataSource,
+ "type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
+ + " AND meta_type=" + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue(),
+ "Unable to get count of directories for datasource, providing empty results");
+ }
+
+ /**
+ * Get count of slack files in a data source.
+ *
+ * @param currentDataSource The data source.
+ *
+ * @return The count.
+ */
+ static Long getCountOfSlackFiles(DataSource currentDataSource) {
+ return getCountOfFiles(currentDataSource,
+ "type=" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType(),
+ "Unable to get count of slack files for datasources, providing empty results");
+ }
+
+ /**
+ * An interface for handling a result set and returning a value.
+ */
+ private interface ResultSetHandler {
+
+ T process(ResultSet resultset) throws SQLException;
+ }
+
+ /**
+ * Retrieves a result based on the provided query.
+ *
+ * @param query The query.
+ * @param processor The result set handler.
+ * @param errorMessage The error message to display if there is an error
+ * retrieving the resultset.
+ *
+ * @return The ResultSetHandler value or null if no ResultSet could be
+ * obtained.
+ */
+ private static T getBaseQueryResult(String query, ResultSetHandler processor, String errorMessage) {
+ try (SleuthkitCase.CaseDbQuery dbQuery = Case.getCurrentCaseThrows().getSleuthkitCase().executeQuery(query)) {
+ ResultSet resultSet = dbQuery.getResultSet();
+ try {
+ return processor.process(resultSet);
+ } catch (SQLException ex) {
+ logger.log(Level.WARNING, errorMessage, ex);
+ }
+ } catch (TskCoreException | NoCurrentCaseException ex) {
+ logger.log(Level.WARNING, errorMessage, ex);
+ }
+ return null;
+ }
+
+ /**
+ * Gets the size of unallocated files in a particular datasource.
+ *
+ * @param currentDataSource The data source.
+ *
+ * @return The size or null if the query could not be executed.
+ */
+ static Long getSizeOfUnallocatedFiles(DataSource currentDataSource) {
+ if (currentDataSource == null) {
+ return null;
+ }
+
+ final String valueParam = "value";
+ final String countParam = "count";
+ String query = "SELECT SUM(size) AS " + valueParam + ", COUNT(*) AS " + countParam
+ + " FROM tsk_files WHERE type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
+ + " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
+ + " AND dir_flags=" + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue()
+ + " AND name<>''"
+ + " AND data_source_obj_id=" + currentDataSource.getId();
+
+ ResultSetHandler handler = (resultSet) -> {
+ if (resultSet.next()) {
+ // ensure that there is an unallocated count result that is attached to this data source
+ long resultCount = resultSet.getLong(valueParam);
+ return (resultCount > 0) ? resultSet.getLong(valueParam) : null;
+ } else {
+ return null;
+ }
+ };
+ String errorMessage = "Unable to get size of unallocated files; returning null.";
+
+ return getBaseQueryResult(query, handler, errorMessage);
+ }
+
+ /**
+ * Generates a result set handler that will return a map of string to long.
+ *
+ * @param keyParam The named parameter in the result set representing the
+ * key.
+ * @param valueParam The named parameter in the result set representing the
+ * value.
+ *
+ * @return The result set handler to generate the map of string to long.
+ */
+ private static ResultSetHandler> getStringLongResultSetHandler(String keyParam, String valueParam) {
+ return (resultSet) -> {
+ LinkedHashMap toRet = new LinkedHashMap<>();
+ while (resultSet.next()) {
+ try {
+ toRet.put(resultSet.getString(keyParam), resultSet.getLong(valueParam));
+ } catch (SQLException ex) {
+ logger.log(Level.WARNING, "Failed to get a result pair from the result set.", ex);
+ }
+ }
+
+ return toRet;
+ };
+ }
+
+ /**
+ * Retrieves counts for each artifact type in a data source.
+ *
+ * @param selectedDataSource The data source.
+ *
+ * @return A mapping of artifact type name to the counts or null if there
+ * was an error executing the query.
+ */
+ static Map getCountsOfArtifactsByType(DataSource selectedDataSource) {
+ if (selectedDataSource == null) {
+ return Collections.emptyMap();
+ }
+
+ final String nameParam = "name";
+ final String valueParam = "value";
+ String query
+ = "SELECT bbt.display_name AS " + nameParam + ", COUNT(*) AS " + valueParam
+ + " FROM blackboard_artifacts bba "
+ + " INNER JOIN blackboard_artifact_types bbt ON bba.artifact_type_id = bbt.artifact_type_id"
+ + " WHERE bba.data_source_obj_id =" + selectedDataSource.getId()
+ + " GROUP BY bbt.display_name";
+
+ String errorMessage = "Unable to get artifact type counts; returning null.";
+ return getBaseQueryResult(query, getStringLongResultSetHandler(nameParam, valueParam), errorMessage);
+ }
+
+ /**
+ * Describes a result of a program run on a datasource.
+ */
+ 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
+ */
+ String getProgramName() {
+ return programName;
+ }
+
+ /**
+ * @return The path of the program.
+ */
+ String getProgramPath() {
+ return programPath;
+ }
+
+ /**
+ * @return The number of run times or null if not present.
+ */
+ Long getRunTimes() {
+ return runTimes;
+ }
+
+ /**
+ * @return The last time the program was run or null if not present.
+ */
+ public Date getLastRun() {
+ return lastRun;
+ }
+ }
+
+ /**
+ * 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";
+
+ /**
+ * 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, 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 clauses) {
+ if (clauses.isEmpty()) {
+ return "";
+ }
+
+ List 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 + "'";
+ }
+
+ /**
+ * 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
+ */
+ static List getTopPrograms(DataSource dataSource, int count) {
+ 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, ATTRIBUTE_TYPE.TSK_PROG_NAME, nameParam, bbaQuery)
+ + getAttributeJoin(JoinType.LEFT, AttributeColumn.value_text, ATTRIBUTE_TYPE.TSK_PATH, pathParam, bbaQuery)
+ + getAttributeJoin(JoinType.LEFT, AttributeColumn.value_int32, ATTRIBUTE_TYPE.TSK_COUNT, runCountParam, bbaQuery)
+ + getAttributeJoin(JoinType.LEFT, AttributeColumn.value_int64, ATTRIBUTE_TYPE.TSK_DATETIME, lastRunParam, bbaQuery)
+ + getWhereString(Arrays.asList(
+ bbaQuery + ".artifact_type_id = " + 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";
+
+ final String errorMessage = "Unable to get top program results; returning null.";
+
+ ResultSetHandler> handler = (resultSet) -> {
+ List progResults = new ArrayList<>();
+
+ boolean quitAtCount = false;
+
+ while (resultSet.next() && (!quitAtCount || progResults.size() < count)) {
+ try {
+ 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));
+
+ } catch (SQLException ex) {
+ logger.log(Level.WARNING, "Failed to get a top program result from the result set.", ex);
+ }
+ }
+
+ return progResults;
+ };
+
+ return getBaseQueryResult(query, handler, errorMessage);
+ }
+
+ /**
+ * Functions that determine the folder name of a list of path elements. If
+ * not matched, function returns null.
+ */
+ private static final List, 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;
+ }
+ );
+
+ /**
+ * Determines a short folder name if any. Otherwise, returns empty string.
+ *
+ * @param strPath The string path.
+ *
+ * @return The short folder name or empty string if not found.
+ */
+ static String getShortFolderName(String strPath, String applicationName) {
+ if (strPath == null) {
+ return "";
+ }
+
+ List 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, String> matchEntry : SHORT_FOLDER_MATCHERS) {
+ String result = matchEntry.apply(pathEls);
+ if (StringUtils.isNotBlank(result)) {
+ return result;
+ }
+ }
+
+ return "";
+ }
+
+ /**
+ * Generates a string which is a concatenation of the value received from
+ * the result set.
+ *
+ * @param query The query.
+ * @param valueParam The parameter for the value in the result set.
+ * @param separator The string separator used in concatenation.
+ * @param errorMessage The error message if the result set could not
+ * be received.
+ * @param singleErrorMessage The error message if a single result could not
+ * be obtained.
+ *
+ * @return The concatenated string or null if the query could not be
+ * executed.
+ */
+ private static String getConcattedStringsResult(String query, String valueParam, String separator, String errorMessage, String singleErrorMessage) {
+ ResultSetHandler handler = (resultSet) -> {
+ String toRet = "";
+ boolean first = true;
+ while (resultSet.next()) {
+ try {
+ if (first) {
+ first = false;
+ } else {
+ toRet += separator;
+ }
+ toRet += resultSet.getString(valueParam);
+ } catch (SQLException ex) {
+ logger.log(Level.WARNING, singleErrorMessage, ex);
+ }
+ }
+
+ return toRet;
+ };
+
+ return getBaseQueryResult(query, handler, errorMessage);
+ }
+
+ /**
+ * Generates a concatenated string value based on the text value of a
+ * particular attribute in a particular artifact for a specific data source.
+ *
+ * @param dataSourceId The data source id.
+ * @param artifactTypeId The artifact type id.
+ * @param attributeTypeId The attribute type id.
+ *
+ * @return The concatenated value or null if the query could not be
+ * executed.
+ */
+ private static String getConcattedAttrValue(long dataSourceId, int artifactTypeId, int attributeTypeId) {
+ final String valueParam = "concatted_attribute_value";
+ String query = "SELECT attr.value_text AS " + valueParam
+ + " FROM blackboard_artifacts bba "
+ + " INNER JOIN blackboard_attributes attr ON bba.artifact_id = attr.artifact_id "
+ + " WHERE bba.data_source_obj_id = " + dataSourceId
+ + " AND bba.artifact_type_id = " + artifactTypeId
+ + " AND attr.attribute_type_id = " + attributeTypeId;
+
+ String errorMessage = "Unable to execute query to retrieve concatted attribute values.";
+ String singleErrorMessage = "There was an error retrieving one of the results. That result will be omitted from concatted value.";
+ String separator = ", ";
+ return getConcattedStringsResult(query, valueParam, separator, errorMessage, singleErrorMessage);
+ }
+
+ /**
+ * Retrieves the concatenation of operating system attributes for a
+ * particular data source.
+ *
+ * @param dataSource The data source.
+ *
+ * @return The concatenated value or null if the query could not be
+ * executed.
+ */
+ static String getOperatingSystems(DataSource dataSource) {
+ if (dataSource == null) {
+ return null;
+ }
+
+ return getConcattedAttrValue(dataSource.getId(),
+ BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_INFO.getTypeID(),
+ BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID());
+ }
+
+ /**
+ * Retrieves the concatenation of data source usage for a particular data
+ * source.
+ *
+ * @param dataSource The data source.
+ *
+ * @return The concatenated value or null if the query could not be
+ * executed.
+ */
+ static String getDataSourceType(DataSource dataSource) {
+ if (dataSource == null) {
+ return null;
+ }
+
+ return getConcattedAttrValue(dataSource.getId(),
+ BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE.getTypeID(),
+ BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID());
+ }
+
+ /**
+ * Get a map containing the TSK_DATA_SOURCE_USAGE description attributes
+ * associated with each data source in the current case.
+ *
+ * @return Collection which maps datasource id to a String which displays a
+ * comma seperated list of values of data source usage types
+ * expected to be in the datasource
+ */
+ static Map getDataSourceTypes() {
+ try {
+ SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
+ List listOfArtifacts = skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE);
+ Map typeMap = new HashMap<>();
+ for (BlackboardArtifact typeArtifact : listOfArtifacts) {
+ BlackboardAttribute descriptionAttr = typeArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION));
+ if (typeArtifact.getDataSource() != null && descriptionAttr != null) {
+ long dsId = typeArtifact.getDataSource().getId();
+ String type = typeMap.get(typeArtifact.getDataSource().getId());
+ if (type == null) {
+ type = descriptionAttr.getValueString();
+ } else {
+ type = type + ", " + descriptionAttr.getValueString();
+ }
+ typeMap.put(dsId, type);
+ }
+ }
+ return typeMap;
+ } catch (TskCoreException | NoCurrentCaseException ex) {
+ logger.log(Level.WARNING, "Unable to get types of files for all datasources, providing empty results", ex);
+ return Collections.emptyMap();
+ }
+ }
+
+ /**
+ * Get a map containing the number of files in each data source in the
+ * current case.
+ *
+ * @return Collection which maps datasource id to a count for the number of
+ * files in the datasource, will only contain entries for
+ * datasources which have at least 1 file
+ */
+ static Map getCountsOfFiles() {
+ try {
+ final String countFilesQuery = "data_source_obj_id, COUNT(*) AS value"
+ + " FROM tsk_files WHERE type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
+ + " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
+ + " AND name<>'' GROUP BY data_source_obj_id"; //NON-NLS
+ return getValuesMap(countFilesQuery);
+ } catch (TskCoreException | NoCurrentCaseException ex) {
+ logger.log(Level.WARNING, "Unable to get counts of files for all datasources, providing empty results", ex);
+ return Collections.emptyMap();
+ }
+ }
+
+ /**
+ * Get a map containing the number of artifacts in each data source in the
+ * current case.
+ *
+ * @return Collection which maps datasource id to a count for the number of
+ * artifacts in the datasource, will only contain entries for
+ * datasources which have at least 1 artifact
+ */
+ static Map getCountsOfArtifacts() {
+ try {
+ final String countArtifactsQuery = "data_source_obj_id, COUNT(*) AS value"
+ + " FROM blackboard_artifacts WHERE review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID()
+ + " GROUP BY data_source_obj_id"; //NON-NLS
+ return getValuesMap(countArtifactsQuery);
+ } catch (TskCoreException | NoCurrentCaseException ex) {
+ logger.log(Level.WARNING, "Unable to get counts of artifacts for all datasources, providing empty results", ex);
+ return Collections.emptyMap();
+ }
+ }
+
+ /**
+ * Get a map containing the number of tags which have been applied in each
+ * data source in the current case. Not necessarily the same as the number
+ * of items tagged, as an item can have any number of tags.
+ *
+ * @return Collection which maps datasource id to a count for the number of
+ * tags which have been applied in the datasource, will only contain
+ * entries for datasources which have at least 1 item tagged.
+ */
+ static Map getCountsOfTags() {
+ try {
+ final String countFileTagsQuery = "data_source_obj_id, COUNT(*) AS value"
+ + " FROM content_tags as content_tags, tsk_files as tsk_files"
+ + " WHERE content_tags.obj_id = tsk_files.obj_id"
+ + " GROUP BY data_source_obj_id"; //NON-NLS
+ //new hashmap so it can be modifiable
+ Map tagCountMap = new HashMap<>(getValuesMap(countFileTagsQuery));
+ final String countArtifactTagsQuery = "data_source_obj_id, COUNT(*) AS value"
+ + " FROM blackboard_artifact_tags as artifact_tags, blackboard_artifacts AS arts"
+ + " WHERE artifact_tags.artifact_id = arts.artifact_id"
+ + " GROUP BY data_source_obj_id"; //NON-NLS
+ //combine the results from the count artifact tags query into the copy of the mapped results from the count file tags query
+ getValuesMap(countArtifactTagsQuery).forEach((key, value) -> tagCountMap.merge(key, value, (value1, value2) -> value1 + value2));
+ return tagCountMap;
+ } catch (TskCoreException | NoCurrentCaseException ex) {
+ logger.log(Level.WARNING, "Unable to get counts of tags for all datasources, providing empty results", ex);
+ return Collections.emptyMap();
+ }
+ }
+
+ /**
+ * Get the number of files in the case database for the current data source
+ * which have the specified mimetypes.
+ *
+ * @param currentDataSource the data source which we are finding a file
+ * count
+ *
+ * @param setOfMimeTypes the set of mime types which we are finding the
+ * number of occurences of
+ *
+ * @return a Long value which represents the number of occurrences of the
+ * specified mime types in the current case for the specified data
+ * source, null if no count was retrieved
+ */
+ static Long getCountOfFilesForMimeTypes(DataSource currentDataSource, Set setOfMimeTypes) {
+ if (currentDataSource != null) {
+ try {
+ String inClause = String.join("', '", setOfMimeTypes);
+ SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
+ return skCase.countFilesWhere("data_source_obj_id=" + currentDataSource.getId()
+ + " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
+ + " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
+ + " AND mime_type IN ('" + inClause + "')"
+ + " AND name<>''");
+ } catch (TskCoreException | NoCurrentCaseException ex) {
+ logger.log(Level.WARNING, "Unable to get count of files for specified mime types", ex);
+ //unable to get count of files for the specified mimetypes cell will be displayed as empty
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Helper method to execute a select query with a
+ * DataSourceSingleValueCallback.
+ *
+ * @param query the portion of the query which should follow the SELECT
+ *
+ * @return a map of datasource object ID to a value of type Long
+ *
+ * @throws TskCoreException
+ * @throws NoCurrentCaseException
+ */
+ private static Map getValuesMap(String query) throws TskCoreException, NoCurrentCaseException {
+ SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
+ DataSourceSingleValueCallback callback = new DataSourceSingleValueCallback();
+ skCase.getCaseDbAccessManager().select(query, callback);
+ return callback.getMapOfValues();
+ }
+
+ /**
+ * Empty private constructor
+ */
+ private DataSourceInfoUtilities() {
+ }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceLabeledValueCallback.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceLabeledValueCallback.java
similarity index 97%
rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceLabeledValueCallback.java
rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceLabeledValueCallback.java
index 6c9c918667..1a44e2a76b 100644
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceLabeledValueCallback.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceLabeledValueCallback.java
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.datasourcesummary.datamodel;
+package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.sql.ResultSet;
import java.sql.SQLException;
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceSingleValueCallback.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSingleValueCallback.java
similarity index 97%
rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceSingleValueCallback.java
rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSingleValueCallback.java
index 6b1ff205fa..fc7eea15e5 100644
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceSingleValueCallback.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSingleValueCallback.java
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.datasourcesummary.datamodel;
+package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.sql.ResultSet;
import java.sql.SQLException;
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummary.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummary.java
similarity index 98%
rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummary.java
rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummary.java
index 1894e8968b..b50c3596bd 100644
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummary.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummary.java
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.datasourcesummary.ui;
+package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.sql.ResultSet;
import java.sql.SQLException;
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryAction.java
similarity index 95%
rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryAction.java
rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryAction.java
index 12a3ed3059..7514d61599 100644
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryAction.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryAction.java
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.datasourcesummary.ui;
+package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
@@ -28,7 +28,6 @@ import org.openide.util.HelpCtx;
import org.openide.util.NbBundle.Messages;
import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.casemodule.Case;
-import org.sleuthkit.autopsy.datasourcesummary.ui.Bundle;
@ActionID(category = "Case", id = "org.sleuthkit.autopsy.casemodule.datasourcesummary.DataSourceSummaryAction")
@ActionRegistration(displayName = "#CTL_DataSourceSummaryAction", lazy = false)
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.form
new file mode 100644
index 0000000000..9a82746da6
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.form
@@ -0,0 +1,120 @@
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryCountsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java
similarity index 53%
rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryCountsPanel.java
rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java
index eff822f161..6bb6603c11 100644
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryCountsPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.datasourcesummary.ui;
+package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.util.Map;
import org.sleuthkit.autopsy.coreutils.Logger;
@@ -24,8 +24,7 @@ import javax.swing.JLabel;
import javax.swing.table.DefaultTableCellRenderer;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
-import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceCountsSummary;
-
+import org.sleuthkit.autopsy.coreutils.FileTypeUtils;
import org.sleuthkit.datamodel.DataSource;
/**
@@ -41,8 +40,6 @@ import org.sleuthkit.datamodel.DataSource;
})
class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
- private static final long serialVersionUID = 1L;
-
// Result returned for a data model if no data found.
private static final Object[][] EMPTY_PAIRS = new Object[][]{};
@@ -64,11 +61,10 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
Bundle.DataSourceSummaryCountsPanel_ArtifactCountsTableModel_count_header()
};
+ private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(DataSourceSummaryCountsPanel.class.getName());
private final DefaultTableCellRenderer rightAlignedRenderer = new DefaultTableCellRenderer();
- private final FileTypePieChart fileTypePieChart = new FileTypePieChart();
-
private DataSource dataSource;
/**
@@ -77,6 +73,7 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
DataSourceSummaryCountsPanel() {
rightAlignedRenderer.setHorizontalAlignment(JLabel.RIGHT);
initComponents();
+ fileCountsByMimeTypeTable.getTableHeader().setReorderingAllowed(false);
fileCountsByCategoryTable.getTableHeader().setReorderingAllowed(false);
artifactCountsTable.getTableHeader().setReorderingAllowed(false);
setDataSource(null);
@@ -99,20 +96,29 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
if (dataSource == null || !Case.isCaseOpen()) {
- updateCountsTableData(EMPTY_PAIRS, EMPTY_PAIRS);
+ updateCountsTableData(EMPTY_PAIRS,
+ EMPTY_PAIRS,
+ EMPTY_PAIRS);
} else {
- updateCountsTableData(getFileCategoryModel(dataSource), getArtifactCountsModel(dataSource));
+ updateCountsTableData(getMimeTypeModel(dataSource),
+ getFileCategoryModel(dataSource),
+ getArtifactCountsModel(dataSource));
}
- this.fileTypePieChart.setDataSource(dataSource);
+
}
/**
* Specify the DataSource to display file information for.
*
+ * @param mimeTypeDataModel The mime type data model.
* @param fileCategoryDataModel The file category data model.
* @param artifactDataModel The artifact type data model.
*/
- private void updateCountsTableData(Object[][] fileCategoryDataModel, Object[][] artifactDataModel) {
+ private void updateCountsTableData(Object[][] mimeTypeDataModel, Object[][] fileCategoryDataModel, Object[][] artifactDataModel) {
+ fileCountsByMimeTypeTable.setModel(new NonEditableTableModel(mimeTypeDataModel, MIME_TYPE_COLUMN_HEADERS));
+ fileCountsByMimeTypeTable.getColumnModel().getColumn(1).setCellRenderer(rightAlignedRenderer);
+ fileCountsByMimeTypeTable.getColumnModel().getColumn(0).setPreferredWidth(130);
+
fileCountsByCategoryTable.setModel(new NonEditableTableModel(fileCategoryDataModel, FILE_BY_CATEGORY_COLUMN_HEADERS));
fileCountsByCategoryTable.getColumnModel().getColumn(1).setCellRenderer(rightAlignedRenderer);
fileCountsByCategoryTable.getColumnModel().getColumn(0).setPreferredWidth(130);
@@ -124,6 +130,48 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
this.repaint();
}
+ /**
+ * Determines the JTable data model for datasource mime types.
+ *
+ * @param dataSource The DataSource.
+ *
+ * @return The model to be used with a JTable.
+ */
+ @Messages({
+ "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.images.row=Images",
+ "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.videos.row=Videos",
+ "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.audio.row=Audio",
+ "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.documents.row=Documents",
+ "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.executables.row=Executables"
+ })
+ private static Object[][] getMimeTypeModel(DataSource dataSource) {
+ return new Object[][]{
+ new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_images_row(),
+ getCount(dataSource, FileTypeUtils.FileTypeCategory.IMAGE)},
+ new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_videos_row(),
+ getCount(dataSource, FileTypeUtils.FileTypeCategory.VIDEO)},
+ new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_audio_row(),
+ getCount(dataSource, FileTypeUtils.FileTypeCategory.AUDIO)},
+ new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_documents_row(),
+ getCount(dataSource, FileTypeUtils.FileTypeCategory.DOCUMENTS)},
+ new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_executables_row(),
+ getCount(dataSource, FileTypeUtils.FileTypeCategory.EXECUTABLE)}
+ };
+ }
+
+ /**
+ * Retrieves the counts of files of a particular mime type for a particular
+ * DataSource.
+ *
+ * @param dataSource The DataSource.
+ * @param category The mime type category.
+ *
+ * @return The count.
+ */
+ private static Long getCount(DataSource dataSource, FileTypeUtils.FileTypeCategory category) {
+ return DataSourceInfoUtilities.getCountOfFilesForMimeTypes(dataSource, category.getMediaTypes());
+ }
+
/**
* Determines the JTable data model for datasource file categories.
*
@@ -139,11 +187,11 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
"DataSourceSummaryCountsPanel.FilesByCategoryTableModel.directory.row=Directory"
})
private static Object[][] getFileCategoryModel(DataSource selectedDataSource) {
- Long fileCount = zeroIfNull(DataSourceCountsSummary.getCountOfFiles(selectedDataSource));
- Long unallocatedFiles = zeroIfNull(DataSourceCountsSummary.getCountOfUnallocatedFiles(selectedDataSource));
- Long allocatedFiles = zeroIfNull(DataSourceCountsSummary.getCountOfAllocatedFiles(selectedDataSource));
- Long slackFiles = zeroIfNull(DataSourceCountsSummary.getCountOfSlackFiles(selectedDataSource));
- Long directories = zeroIfNull(DataSourceCountsSummary.getCountOfDirectories(selectedDataSource));
+ Long fileCount = zeroIfNull(DataSourceInfoUtilities.getCountOfFiles(selectedDataSource));
+ Long unallocatedFiles = zeroIfNull(DataSourceInfoUtilities.getCountOfUnallocatedFiles(selectedDataSource));
+ Long allocatedFiles = zeroIfNull(getAllocatedCount(fileCount, unallocatedFiles));
+ Long slackFiles = zeroIfNull(DataSourceInfoUtilities.getCountOfSlackFiles(selectedDataSource));
+ Long directories = zeroIfNull(DataSourceInfoUtilities.getCountOfDirectories(selectedDataSource));
return new Object[][]{
new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_all_row(), fileCount},
@@ -165,6 +213,24 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
return origValue == null ? 0 : origValue;
}
+ /**
+ * Safely gets the allocated files count.
+ *
+ * @param allFilesCount The count of all files.
+ * @param unallocatedFilesCount The count of unallocated files.
+ *
+ * @return The count of allocated files.
+ */
+ private static long getAllocatedCount(Long allFilesCount, Long unallocatedFilesCount) {
+ if (allFilesCount == null) {
+ return 0;
+ } else if (unallocatedFilesCount == null) {
+ return allFilesCount;
+ } else {
+ return allFilesCount - unallocatedFilesCount;
+ }
+ }
+
/**
* The counts of different artifact types found in a DataSource.
*
@@ -173,7 +239,7 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
* @return The JTable data model of counts of artifact types.
*/
private static Object[][] getArtifactCountsModel(DataSource selectedDataSource) {
- Map artifactMapping = DataSourceCountsSummary.getCountsOfArtifactsByType(selectedDataSource);
+ Map artifactMapping = DataSourceInfoUtilities.getCountsOfArtifactsByType(selectedDataSource);
if (artifactMapping == null) {
return EMPTY_PAIRS;
}
@@ -194,120 +260,83 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
// //GEN-BEGIN:initComponents
private void initComponents() {
- javax.swing.JScrollPane scrollParent = new javax.swing.JScrollPane();
- javax.swing.JPanel parentPanel = new javax.swing.JPanel();
- javax.swing.JScrollPane fileCountsByCategoryScrollPane = new javax.swing.JScrollPane();
+ fileCountsByMimeTypeScrollPane = new javax.swing.JScrollPane();
+ fileCountsByMimeTypeTable = new javax.swing.JTable();
+ byMimeTypeLabel = new javax.swing.JLabel();
+ fileCountsByCategoryScrollPane = new javax.swing.JScrollPane();
fileCountsByCategoryTable = new javax.swing.JTable();
- javax.swing.JLabel byCategoryLabel = new javax.swing.JLabel();
- javax.swing.JLabel resultsByTypeLabel = new javax.swing.JLabel();
- javax.swing.JScrollPane artifactCountsScrollPane = new javax.swing.JScrollPane();
+ byCategoryLabel = new javax.swing.JLabel();
+ jLabel1 = new javax.swing.JLabel();
+ artifactCountsScrollPane = new javax.swing.JScrollPane();
artifactCountsTable = new javax.swing.JTable();
- javax.swing.JPanel fileTypePiePanel = fileTypePieChart;
- javax.swing.JPanel filesByCatParent = new javax.swing.JPanel();
- javax.swing.JPanel resultsByTypeParent = new javax.swing.JPanel();
- parentPanel.setMinimumSize(new java.awt.Dimension(840, 320));
+ fileCountsByMimeTypeScrollPane.setViewportView(fileCountsByMimeTypeTable);
+
+ org.openide.awt.Mnemonics.setLocalizedText(byMimeTypeLabel, org.openide.util.NbBundle.getMessage(DataSourceSummaryCountsPanel.class, "DataSourceSummaryCountsPanel.byMimeTypeLabel.text")); // NOI18N
fileCountsByCategoryScrollPane.setViewportView(fileCountsByCategoryTable);
org.openide.awt.Mnemonics.setLocalizedText(byCategoryLabel, org.openide.util.NbBundle.getMessage(DataSourceSummaryCountsPanel.class, "DataSourceSummaryCountsPanel.byCategoryLabel.text")); // NOI18N
- org.openide.awt.Mnemonics.setLocalizedText(resultsByTypeLabel, org.openide.util.NbBundle.getMessage(DataSourceSummaryCountsPanel.class, "DataSourceSummaryCountsPanel.resultsByTypeLabel.text")); // NOI18N
+ org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(DataSourceSummaryCountsPanel.class, "DataSourceSummaryCountsPanel.jLabel1.text")); // NOI18N
- artifactCountsTable.setAutoCreateRowSorter(true);
artifactCountsScrollPane.setViewportView(artifactCountsTable);
- fileTypePiePanel.setPreferredSize(new java.awt.Dimension(400, 300));
-
- javax.swing.GroupLayout filesByCatParentLayout = new javax.swing.GroupLayout(filesByCatParent);
- filesByCatParent.setLayout(filesByCatParentLayout);
- filesByCatParentLayout.setHorizontalGroup(
- filesByCatParentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGap(0, 0, Short.MAX_VALUE)
- );
- filesByCatParentLayout.setVerticalGroup(
- filesByCatParentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGap(0, 0, Short.MAX_VALUE)
- );
-
- javax.swing.GroupLayout resultsByTypeParentLayout = new javax.swing.GroupLayout(resultsByTypeParent);
- resultsByTypeParent.setLayout(resultsByTypeParentLayout);
- resultsByTypeParentLayout.setHorizontalGroup(
- resultsByTypeParentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGap(0, 0, Short.MAX_VALUE)
- );
- resultsByTypeParentLayout.setVerticalGroup(
- resultsByTypeParentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGap(0, 0, Short.MAX_VALUE)
- );
-
- javax.swing.GroupLayout parentPanelLayout = new javax.swing.GroupLayout(parentPanel);
- parentPanel.setLayout(parentPanelLayout);
- parentPanelLayout.setHorizontalGroup(
- parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(parentPanelLayout.createSequentialGroup()
- .addContainerGap()
- .addComponent(fileTypePiePanel, javax.swing.GroupLayout.PREFERRED_SIZE, 400, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addGap(18, 18, 18)
- .addGroup(parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(fileCountsByCategoryScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 140, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addComponent(byCategoryLabel)
- .addComponent(filesByCatParent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addGap(18, 18, 18)
- .addGroup(parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(resultsByTypeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addGroup(parentPanelLayout.createSequentialGroup()
- .addComponent(artifactCountsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 244, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(resultsByTypeParent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
- .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
- );
- parentPanelLayout.setVerticalGroup(
- parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(parentPanelLayout.createSequentialGroup()
- .addContainerGap()
- .addGroup(parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(parentPanelLayout.createSequentialGroup()
- .addComponent(fileTypePiePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
- .addGroup(parentPanelLayout.createSequentialGroup()
- .addGroup(parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(byCategoryLabel)
- .addComponent(resultsByTypeLabel))
- .addGroup(parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, parentPanelLayout.createSequentialGroup()
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- .addComponent(resultsByTypeParent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addGap(148, 148, 148))
- .addGroup(parentPanelLayout.createSequentialGroup()
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addGroup(parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(artifactCountsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
- .addGroup(parentPanelLayout.createSequentialGroup()
- .addComponent(fileCountsByCategoryScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 107, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addGap(31, 31, 31)
- .addComponent(filesByCatParent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addGap(0, 0, Short.MAX_VALUE)))
- .addContainerGap())))))
- );
-
- scrollParent.setViewportView(parentPanel);
-
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(scrollParent)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addComponent(fileCountsByMimeTypeScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE)
+ .addComponent(byMimeTypeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addGap(18, 18, 18)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(byCategoryLabel)
+ .addComponent(fileCountsByCategoryScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGap(18, 18, 18)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(artifactCountsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 244, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
+
+ layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {fileCountsByCategoryScrollPane, fileCountsByMimeTypeScrollPane});
+
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(scrollParent)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(byMimeTypeLabel)
+ .addComponent(byCategoryLabel)
+ .addComponent(jLabel1))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(artifactCountsScrollPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(fileCountsByMimeTypeScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 107, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(fileCountsByCategoryScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 86, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGap(0, 0, Short.MAX_VALUE)))
+ .addContainerGap())
);
+
+ layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {fileCountsByCategoryScrollPane, fileCountsByMimeTypeScrollPane});
+
}// //GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JScrollPane artifactCountsScrollPane;
private javax.swing.JTable artifactCountsTable;
+ private javax.swing.JLabel byCategoryLabel;
+ private javax.swing.JLabel byMimeTypeLabel;
+ private javax.swing.JScrollPane fileCountsByCategoryScrollPane;
private javax.swing.JTable fileCountsByCategoryTable;
+ private javax.swing.JScrollPane fileCountsByMimeTypeScrollPane;
+ private javax.swing.JTable fileCountsByMimeTypeTable;
+ private javax.swing.JLabel jLabel1;
// End of variables declaration//GEN-END:variables
}
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryDetailsPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.form
similarity index 84%
rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryDetailsPanel.form
rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.form
index a882623946..9efc00faa0 100644
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryDetailsPanel.form
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.form
@@ -40,7 +40,7 @@
-
+
@@ -52,7 +52,7 @@
-
+
@@ -64,7 +64,7 @@
-
+
@@ -76,7 +76,7 @@
-
+
@@ -88,10 +88,10 @@
-
+
-
+
@@ -103,7 +103,7 @@
-
+
@@ -115,7 +115,7 @@
-
+
@@ -127,7 +127,7 @@
-
+
@@ -139,10 +139,10 @@
-
+
-
+
@@ -179,7 +179,7 @@
-
+
@@ -196,7 +196,7 @@
-
+
@@ -208,7 +208,7 @@
-
+
@@ -220,10 +220,10 @@
-
+
-
+
@@ -235,10 +235,10 @@
-
+
-
+
@@ -250,7 +250,7 @@
-
+
@@ -262,7 +262,7 @@
-
+
@@ -274,7 +274,7 @@
-
+
@@ -286,7 +286,7 @@
-
+
@@ -298,7 +298,7 @@
-
+
@@ -310,7 +310,7 @@
-
+
@@ -322,7 +322,7 @@
-
+
@@ -334,7 +334,7 @@
-
+
@@ -346,7 +346,7 @@
-
+
@@ -358,7 +358,7 @@
-
+
@@ -370,7 +370,7 @@
-
+
@@ -382,7 +382,7 @@
-
+
@@ -394,7 +394,7 @@
-
+
@@ -424,7 +424,7 @@
-
+
@@ -466,7 +466,7 @@
-
+
@@ -478,7 +478,7 @@
-
+
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.java
similarity index 99%
rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryDetailsPanel.java
rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.java
index f1972d9d89..21caa2c4b8 100644
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryDetailsPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.java
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.datasourcesummary.ui;
+package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.text.DecimalFormat;
import java.util.logging.Level;
@@ -25,7 +25,6 @@ import javax.swing.table.DefaultTableModel;
import org.apache.commons.lang3.StringUtils;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
-import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceDetailsSummary;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.TskCoreException;
@@ -74,9 +73,9 @@ class DataSourceSummaryDetailsPanel extends javax.swing.JPanel {
updateDetailsPanelData(null, null, null, null);
} else {
updateDetailsPanelData(dataSource,
- DataSourceDetailsSummary.getSizeOfUnallocatedFiles(dataSource),
- DataSourceDetailsSummary.getOperatingSystems(dataSource),
- DataSourceDetailsSummary.getDataSourceType(dataSource));
+ DataSourceInfoUtilities.getSizeOfUnallocatedFiles(dataSource),
+ DataSourceInfoUtilities.getOperatingSystems(dataSource),
+ DataSourceInfoUtilities.getDataSourceType(dataSource));
}
}
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryDialog.form b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.form
similarity index 92%
rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryDialog.form
rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.form
index d4edf4b0ee..272fc9b041 100644
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryDialog.form
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.form
@@ -22,7 +22,7 @@
-
+
@@ -36,7 +36,7 @@
-
+
@@ -48,7 +48,7 @@
-
+
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.java
similarity index 94%
rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryDialog.java
rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.java
index 1bc033822d..9cd7549c06 100644
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryDialog.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.java
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.datasourcesummary.ui;
+package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.awt.Frame;
import java.beans.PropertyChangeEvent;
@@ -27,7 +27,6 @@ import java.util.Observer;
import java.util.Set;
import javax.swing.event.ListSelectionEvent;
import org.openide.util.NbBundle.Messages;
-import org.sleuthkit.autopsy.datasourcesummary.datamodel.CaseDataSourcesSummary;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent;
import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent.Reason;
@@ -54,8 +53,8 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
})
DataSourceSummaryDialog(Frame owner) {
super(owner, Bundle.DataSourceSummaryDialog_window_title(), true);
- Map usageMap = CaseDataSourcesSummary.getDataSourceTypes();
- Map fileCountsMap = CaseDataSourcesSummary.getCountsOfFiles();
+ Map usageMap = DataSourceInfoUtilities.getDataSourceTypes();
+ Map fileCountsMap = DataSourceInfoUtilities.getCountsOfFiles();
dataSourcesPanel = new DataSourceBrowser(usageMap, fileCountsMap);
dataSourceSummaryTabbedPane = new DataSourceSummaryTabbedPane();
initComponents();
@@ -126,7 +125,7 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
- .addComponent(dataSourceSummarySplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 860, Short.MAX_VALUE)
+ .addComponent(dataSourceSummarySplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 668, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(closeButton)))
@@ -136,7 +135,7 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
- .addComponent(dataSourceSummarySplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 540, Short.MAX_VALUE)
+ .addComponent(dataSourceSummarySplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 362, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(closeButton)
.addContainerGap())
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryNode.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryNode.java
similarity index 98%
rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryNode.java
rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryNode.java
index a4c48e7adf..0411d94bb2 100644
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryNode.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryNode.java
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.datasourcesummary.ui;
+package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
@@ -30,7 +30,6 @@ import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.Sheet;
import org.openide.util.NbBundle.Messages;
-import org.sleuthkit.autopsy.datasourcesummary.ui.Bundle;
import org.sleuthkit.autopsy.datamodel.NodeProperty;
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
import org.sleuthkit.datamodel.DataSource;
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryTabbedPane.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryTabbedPane.java
similarity index 96%
rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryTabbedPane.java
rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryTabbedPane.java
index 9298646a9d..dddc4ee123 100644
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryTabbedPane.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryTabbedPane.java
@@ -16,12 +16,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.datasourcesummary.ui;
+package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import javax.swing.JTabbedPane;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.IngestJobInfoPanel;
-import org.sleuthkit.autopsy.datasourcesummary.ui.Bundle;
import org.sleuthkit.datamodel.DataSource;
/**
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryUserActivityPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryUserActivityPanel.form
similarity index 92%
rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryUserActivityPanel.form
rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryUserActivityPanel.form
index 0829b9e045..b938286e96 100644
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryUserActivityPanel.form
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryUserActivityPanel.form
@@ -42,7 +42,7 @@
-
+
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryUserActivityPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryUserActivityPanel.java
similarity index 94%
rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryUserActivityPanel.java
rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryUserActivityPanel.java
index 21b2a30f22..c97e2ec18c 100644
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryUserActivityPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryUserActivityPanel.java
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.datasourcesummary.ui;
+package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.awt.Component;
import java.text.DateFormat;
@@ -32,8 +32,6 @@ import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
-import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceTopProgramsSummary;
-import org.sleuthkit.autopsy.datasourcesummary.datamodel.TopProgramsResult;
import org.sleuthkit.datamodel.DataSource;
/**
@@ -116,8 +114,8 @@ public class DataSourceSummaryUserActivityPanel extends javax.swing.JPanel {
* @return The JTable data model of counts of program runs.
*/
private static TopProgramsModel getTopProgramsModel(DataSource selectedDataSource) {
- List topProgramList
- = DataSourceTopProgramsSummary.getTopPrograms(selectedDataSource, TOP_PROGS_COUNT);
+ List topProgramList
+ = DataSourceInfoUtilities.getTopPrograms(selectedDataSource, TOP_PROGS_COUNT);
if (topProgramList == null) {
return new TopProgramsModel(null);
@@ -196,14 +194,14 @@ public class DataSourceSummaryUserActivityPanel extends javax.swing.JPanel {
Bundle.DataSourceSummaryUserActivityPanel_TopProgramsTableModel_lastrun_header()
};
- private final List programResults;
+ private final List programResults;
/**
* Main constructor.
*
* @param programResults The results to display.
*/
- TopProgramsModel(List programResults) {
+ TopProgramsModel(List programResults) {
this.programResults = programResults == null ? new ArrayList<>() : Collections.unmodifiableList(programResults);
}
@@ -228,12 +226,12 @@ public class DataSourceSummaryUserActivityPanel extends javax.swing.JPanel {
return null;
}
- TopProgramsResult result = programResults.get(rowIndex);
+ DataSourceInfoUtilities.TopProgramsResult result = programResults.get(rowIndex);
switch (columnIndex) {
case 0:
return new ProgramNameCellValue(result.getProgramName(), result.getProgramPath());
case 1:
- return DataSourceTopProgramsSummary.getShortFolderName(result.getProgramPath(), result.getProgramName());
+ return DataSourceInfoUtilities.getShortFolderName(result.getProgramPath(), result.getProgramName());
case 2:
return result.getRunTimes();
case 3:
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/NonEditableTableModel.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/NonEditableTableModel.java
similarity index 94%
rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/NonEditableTableModel.java
rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/NonEditableTableModel.java
index 3274415a89..8ed965e2ab 100644
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/NonEditableTableModel.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/NonEditableTableModel.java
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.datasourcesummary.ui;
+package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import javax.swing.table.DefaultTableModel;
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RightAlignedTableCellRenderer.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/RightAlignedTableCellRenderer.java
similarity index 97%
rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RightAlignedTableCellRenderer.java
rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/RightAlignedTableCellRenderer.java
index 989e97da82..12f111bba2 100644
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RightAlignedTableCellRenderer.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/RightAlignedTableCellRenderer.java
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.datasourcesummary.ui;
+package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.awt.Component;
import java.lang.reflect.InvocationTargetException;
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ViewSummaryInformationAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/ViewSummaryInformationAction.java
similarity index 95%
rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ViewSummaryInformationAction.java
rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/ViewSummaryInformationAction.java
index c62cb8c214..babe2197a1 100644
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ViewSummaryInformationAction.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/ViewSummaryInformationAction.java
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.datasourcesummary.ui;
+package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.awt.Frame;
import java.awt.event.ActionEvent;
@@ -24,7 +24,6 @@ import javax.swing.AbstractAction;
import javax.swing.SwingUtilities;
import org.openide.util.NbBundle.Messages;
import org.openide.windows.WindowManager;
-import org.sleuthkit.autopsy.datasourcesummary.ui.Bundle;
/**
* ViewSummaryInformationAction action for opening a Data Sources Summary Dialog
diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java
index 06a50eb788..f668893eb1 100644
--- a/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java
+++ b/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java
@@ -36,7 +36,7 @@ import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.DeleteDataSourceAction;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
-import org.sleuthkit.autopsy.datasourcesummary.ui.ViewSummaryInformationAction;
+import org.sleuthkit.autopsy.casemodule.datasourcesummary.ViewSummaryInformationAction;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
import org.sleuthkit.autopsy.coreutils.Logger;
diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/SpecialDirectoryNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/SpecialDirectoryNode.java
index a3c6691ba2..ca73a64468 100644
--- a/Core/src/org/sleuthkit/autopsy/datamodel/SpecialDirectoryNode.java
+++ b/Core/src/org/sleuthkit/autopsy/datamodel/SpecialDirectoryNode.java
@@ -24,7 +24,7 @@ import java.util.List;
import javax.swing.Action;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.DeleteDataSourceAction;
-import org.sleuthkit.autopsy.datasourcesummary.ui.ViewSummaryInformationAction;
+import org.sleuthkit.autopsy.casemodule.datasourcesummary.ViewSummaryInformationAction;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.directorytree.ExportCSVAction;
import org.sleuthkit.autopsy.directorytree.ExtractAction;
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/CaseDataSourcesSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/CaseDataSourcesSummary.java
deleted file mode 100644
index 50e883e29a..0000000000
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/CaseDataSourcesSummary.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Autopsy Forensic Browser
- *
- * Copyright 2020 Basis Technology Corp.
- * Contact: carrier sleuthkit 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 java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.logging.Level;
-import org.sleuthkit.autopsy.casemodule.Case;
-import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
-import org.sleuthkit.autopsy.coreutils.Logger;
-import org.sleuthkit.datamodel.BlackboardArtifact;
-import org.sleuthkit.datamodel.BlackboardAttribute;
-import org.sleuthkit.datamodel.SleuthkitCase;
-import org.sleuthkit.datamodel.TskCoreException;
-import org.sleuthkit.datamodel.TskData;
-
-/**
- * Provides methods to query for information for all datasources in a case.
- */
-public class CaseDataSourcesSummary {
-
- private static final Logger logger = Logger.getLogger(CaseDataSourcesSummary.class.getName());
-
- /**
- * Get a map containing the TSK_DATA_SOURCE_USAGE description attributes
- * associated with each data source in the current case.
- *
- * @return Collection which maps datasource id to a String which displays a
- * comma seperated list of values of data source usage types
- * expected to be in the datasource
- */
- public static Map getDataSourceTypes() {
- try {
- SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
- List listOfArtifacts = skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE);
- Map typeMap = new HashMap<>();
- for (BlackboardArtifact typeArtifact : listOfArtifacts) {
- BlackboardAttribute descriptionAttr = typeArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION));
- if (typeArtifact.getDataSource() != null && descriptionAttr != null) {
- long dsId = typeArtifact.getDataSource().getId();
- String type = typeMap.get(typeArtifact.getDataSource().getId());
- if (type == null) {
- type = descriptionAttr.getValueString();
- } else {
- type = type + ", " + descriptionAttr.getValueString();
- }
- typeMap.put(dsId, type);
- }
- }
- return typeMap;
- } catch (TskCoreException | NoCurrentCaseException ex) {
- logger.log(Level.WARNING, "Unable to get types of files for all datasources, providing empty results", ex);
- return Collections.emptyMap();
- }
- }
-
- /**
- * Get a map containing the number of files in each data source in the
- * current case.
- *
- * @return Collection which maps datasource id to a count for the number of
- * files in the datasource, will only contain entries for
- * datasources which have at least 1 file
- */
- public static Map getCountsOfFiles() {
- try {
- final String countFilesQuery = "data_source_obj_id, COUNT(*) AS value FROM tsk_files"
- + " WHERE meta_type=" + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue()
- + " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
- + " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
- + " AND name<>''"
- + " GROUP BY data_source_obj_id"; //NON-NLS
- return getValuesMap(countFilesQuery);
- } catch (TskCoreException | NoCurrentCaseException ex) {
- logger.log(Level.WARNING, "Unable to get counts of files for all datasources, providing empty results", ex);
- return Collections.emptyMap();
- }
- }
-
- /**
- * Get a map containing the number of artifacts in each data source in the
- * current case.
- *
- * @return Collection which maps datasource id to a count for the number of
- * artifacts in the datasource, will only contain entries for
- * datasources which have at least 1 artifact
- */
- public static Map getCountsOfArtifacts() {
- try {
- final String countArtifactsQuery = "data_source_obj_id, COUNT(*) AS value"
- + " FROM blackboard_artifacts WHERE review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID()
- + " GROUP BY data_source_obj_id"; //NON-NLS
- return getValuesMap(countArtifactsQuery);
- } catch (TskCoreException | NoCurrentCaseException ex) {
- logger.log(Level.WARNING, "Unable to get counts of artifacts for all datasources, providing empty results", ex);
- return Collections.emptyMap();
- }
- }
-
- /**
- * Get a map containing the number of tags which have been applied in each
- * data source in the current case. Not necessarily the same as the number
- * of items tagged, as an item can have any number of tags.
- *
- * @return Collection which maps datasource id to a count for the number of
- * tags which have been applied in the datasource, will only contain
- * entries for datasources which have at least 1 item tagged.
- */
- public static Map getCountsOfTags() {
- try {
- final String countFileTagsQuery = "data_source_obj_id, COUNT(*) AS value"
- + " FROM content_tags as content_tags, tsk_files as tsk_files"
- + " WHERE content_tags.obj_id = tsk_files.obj_id"
- + " GROUP BY data_source_obj_id"; //NON-NLS
- //new hashmap so it can be modifiable
- Map tagCountMap = new HashMap<>(getValuesMap(countFileTagsQuery));
- final String countArtifactTagsQuery = "data_source_obj_id, COUNT(*) AS value"
- + " FROM blackboard_artifact_tags as artifact_tags, blackboard_artifacts AS arts"
- + " WHERE artifact_tags.artifact_id = arts.artifact_id"
- + " GROUP BY data_source_obj_id"; //NON-NLS
- //combine the results from the count artifact tags query into the copy of the mapped results from the count file tags query
- getValuesMap(countArtifactTagsQuery).forEach((key, value) -> tagCountMap.merge(key, value, (value1, value2) -> value1 + value2));
- return tagCountMap;
- } catch (TskCoreException | NoCurrentCaseException ex) {
- logger.log(Level.WARNING, "Unable to get counts of tags for all datasources, providing empty results", ex);
- return Collections.emptyMap();
- }
- }
-
- /**
- * Helper method to execute a select query with a
- * DataSourceSingleValueCallback.
- *
- * @param query the portion of the query which should follow the SELECT
- *
- * @return a map of datasource object ID to a value of type Long
- *
- * @throws TskCoreException
- * @throws NoCurrentCaseException
- */
- private static Map getValuesMap(String query) throws TskCoreException, NoCurrentCaseException {
- SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
- DataSourceSingleValueCallback callback = new DataSourceSingleValueCallback();
- skCase.getCaseDbAccessManager().select(query, callback);
- return callback.getMapOfValues();
- }
-
- private CaseDataSourcesSummary() {
- }
-}
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceCountsSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceCountsSummary.java
deleted file mode 100644
index 0f2826636b..0000000000
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceCountsSummary.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Autopsy Forensic Browser
- *
- * Copyright 2019 - 2020 Basis Technology Corp.
- * Contact: carrier sleuthkit 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 java.sql.SQLException;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.logging.Level;
-import org.sleuthkit.autopsy.coreutils.Logger;
-import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceInfoUtilities.ResultSetHandler;
-import org.sleuthkit.datamodel.DataSource;
-import org.sleuthkit.datamodel.TskData;
-
-/**
- * Provides information for the DataSourceSummaryCountsPanel.
- */
-public class DataSourceCountsSummary {
-
- private static final Logger logger = Logger.getLogger(DataSourceCountsSummary.class.getName());
-
- /**
- * Get count of regular files (not directories) in a data source.
- *
- * @param currentDataSource The data source.
- *
- * @return The count.
- */
- public static Long getCountOfFiles(DataSource currentDataSource) {
- return DataSourceInfoUtilities.getCountOfRegularFiles(currentDataSource, null,
- "Unable to get count of files, providing empty results");
- }
-
- /**
- * Get count of allocated files in a data source.
- *
- * @param currentDataSource The data source.
- *
- * @return The count.
- */
- public static Long getCountOfAllocatedFiles(DataSource currentDataSource) {
- return DataSourceInfoUtilities.getCountOfRegularFiles(currentDataSource,
- DataSourceInfoUtilities.getMetaFlagsContainsStatement(TskData.TSK_FS_META_FLAG_ENUM.ALLOC),
- "Unable to get counts of unallocated files for datasource, providing empty results");
- }
-
- /**
- * Get count of unallocated files in a data source.
- *
- * @param currentDataSource The data source.
- *
- * @return The count.
- */
- public static Long getCountOfUnallocatedFiles(DataSource currentDataSource) {
- return DataSourceInfoUtilities.getCountOfRegularFiles(currentDataSource,
- DataSourceInfoUtilities.getMetaFlagsContainsStatement(TskData.TSK_FS_META_FLAG_ENUM.UNALLOC)
- + " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType(),
- "Unable to get counts of unallocated files for datasource, providing empty results");
- }
-
- /**
- * Get count of directories in a data source.
- *
- * @param currentDataSource The data source.
- *
- * @return The count.
- */
- public static Long getCountOfDirectories(DataSource currentDataSource) {
- return DataSourceInfoUtilities.getCountOfTskFiles(currentDataSource,
- "meta_type=" + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue()
- + " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType(),
- "Unable to get count of directories for datasource, providing empty results");
- }
-
- /**
- * Get count of slack files in a data source.
- *
- * @param currentDataSource The data source.
- *
- * @return The count.
- */
- public static Long getCountOfSlackFiles(DataSource currentDataSource) {
- return DataSourceInfoUtilities.getCountOfRegularFiles(currentDataSource,
- DataSourceInfoUtilities.getMetaFlagsContainsStatement(TskData.TSK_FS_META_FLAG_ENUM.UNALLOC)
- + " AND type=" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType(),
- "Unable to get count of slack files for datasources, providing empty results");
- }
-
- /**
- * Retrieves counts for each artifact type in a data source.
- *
- * @param selectedDataSource The data source.
- *
- * @return A mapping of artifact type name to the counts or null if there
- * was an error executing the query.
- */
- public static Map getCountsOfArtifactsByType(DataSource selectedDataSource) {
- if (selectedDataSource == null) {
- return Collections.emptyMap();
- }
-
- final String nameParam = "name";
- final String valueParam = "value";
- String query
- = "SELECT bbt.display_name AS " + nameParam + ", COUNT(*) AS " + valueParam
- + " FROM blackboard_artifacts bba "
- + " INNER JOIN blackboard_artifact_types bbt ON bba.artifact_type_id = bbt.artifact_type_id"
- + " WHERE bba.data_source_obj_id =" + selectedDataSource.getId()
- + " GROUP BY bbt.display_name";
-
- String errorMessage = "Unable to get artifact type counts; returning null.";
- return DataSourceInfoUtilities.getBaseQueryResult(query,
- getStringLongResultSetHandler(nameParam, valueParam),
- errorMessage);
- }
-
- /**
- * Generates a result set handler that will return a map of string to long.
- *
- * @param keyParam The named parameter in the result set representing the
- * key.
- * @param valueParam The named parameter in the result set representing the
- * value.
- *
- * @return The result set handler to generate the map of string to long.
- */
- private static ResultSetHandler> getStringLongResultSetHandler(String keyParam, String valueParam) {
- return (resultSet) -> {
- LinkedHashMap toRet = new LinkedHashMap<>();
- while (resultSet.next()) {
- try {
- toRet.put(resultSet.getString(keyParam), resultSet.getLong(valueParam));
- } catch (SQLException ex) {
- logger.log(Level.WARNING, "Failed to get a result pair from the result set.", ex);
- }
- }
-
- return toRet;
- };
- }
-
- private DataSourceCountsSummary() {
- }
-}
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceDetailsSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceDetailsSummary.java
deleted file mode 100644
index 3dd50131e5..0000000000
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceDetailsSummary.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Autopsy Forensic Browser
- *
- * Copyright 2020 Basis Technology Corp.
- * Contact: carrier sleuthkit 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 java.sql.SQLException;
-import java.util.logging.Level;
-import org.sleuthkit.autopsy.coreutils.Logger;
-import static org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceInfoUtilities.getBaseQueryResult;
-import org.sleuthkit.datamodel.BlackboardArtifact;
-import org.sleuthkit.datamodel.BlackboardAttribute;
-import org.sleuthkit.datamodel.DataSource;
-import org.sleuthkit.datamodel.TskData;
-
-/**
- * Provides methods to query for data source overview details.
- */
-public class DataSourceDetailsSummary {
-
- private static final Logger logger = Logger.getLogger(DataSourceDetailsSummary.class.getName());
-
- /**
- * Gets the size of unallocated files in a particular datasource.
- *
- * @param currentDataSource The data source.
- *
- * @return The size or null if the query could not be executed.
- */
- public static Long getSizeOfUnallocatedFiles(DataSource currentDataSource) {
- if (currentDataSource == null) {
- return null;
- }
-
- final String valueParam = "value";
- final String countParam = "count";
- String query = "SELECT SUM(size) AS " + valueParam + ", COUNT(*) AS " + countParam
- + " FROM tsk_files"
- + " WHERE " + DataSourceInfoUtilities.getMetaFlagsContainsStatement(TskData.TSK_FS_META_FLAG_ENUM.UNALLOC)
- + " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType()
- + " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
- + " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
- + " AND name<>''"
- + " AND data_source_obj_id=" + currentDataSource.getId();
-
- DataSourceInfoUtilities.ResultSetHandler handler = (resultSet) -> {
- if (resultSet.next()) {
- // ensure that there is an unallocated count result that is attached to this data source
- long resultCount = resultSet.getLong(valueParam);
- return (resultCount > 0) ? resultSet.getLong(valueParam) : null;
- } else {
- return null;
- }
- };
- String errorMessage = "Unable to get size of unallocated files; returning null.";
-
- return DataSourceInfoUtilities.getBaseQueryResult(query, handler, errorMessage);
- }
-
- /**
- * Retrieves the concatenation of operating system attributes for a
- * particular data source.
- *
- * @param dataSource The data source.
- *
- * @return The concatenated value or null if the query could not be
- * executed.
- */
- public static String getOperatingSystems(DataSource dataSource) {
- if (dataSource == null) {
- return null;
- }
-
- return getConcattedAttrValue(dataSource.getId(),
- BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_INFO.getTypeID(),
- BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID());
- }
-
- /**
- * Retrieves the concatenation of data source usage for a particular data
- * source.
- *
- * @param dataSource The data source.
- *
- * @return The concatenated value or null if the query could not be
- * executed.
- */
- public static String getDataSourceType(DataSource dataSource) {
- if (dataSource == null) {
- return null;
- }
-
- return getConcattedAttrValue(dataSource.getId(),
- BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE.getTypeID(),
- BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID());
- }
-
- /**
- * Generates a string which is a concatenation of the value received from
- * the result set.
- *
- * @param query The query.
- * @param valueParam The parameter for the value in the result set.
- * @param separator The string separator used in concatenation.
- * @param errorMessage The error message if the result set could not
- * be received.
- * @param singleErrorMessage The error message if a single result could not
- * be obtained.
- *
- * @return The concatenated string or null if the query could not be
- * executed.
- */
- private static String getConcattedStringsResult(String query, String valueParam, String separator, String errorMessage, String singleErrorMessage) {
- DataSourceInfoUtilities.ResultSetHandler handler = (resultSet) -> {
- String toRet = "";
- boolean first = true;
- while (resultSet.next()) {
- try {
- if (first) {
- first = false;
- } else {
- toRet += separator;
- }
- toRet += resultSet.getString(valueParam);
- } catch (SQLException ex) {
- logger.log(Level.WARNING, singleErrorMessage, ex);
- }
- }
-
- return toRet;
- };
-
- return getBaseQueryResult(query, handler, errorMessage);
- }
-
- /**
- * Generates a concatenated string value based on the text value of a
- * particular attribute in a particular artifact for a specific data source.
- *
- * @param dataSourceId The data source id.
- * @param artifactTypeId The artifact type id.
- * @param attributeTypeId The attribute type id.
- *
- * @return The concatenated value or null if the query could not be
- * executed.
- */
- private static String getConcattedAttrValue(long dataSourceId, int artifactTypeId, int attributeTypeId) {
- final String valueParam = "concatted_attribute_value";
- String query = "SELECT attr.value_text AS " + valueParam
- + " FROM blackboard_artifacts bba "
- + " INNER JOIN blackboard_attributes attr ON bba.artifact_id = attr.artifact_id "
- + " WHERE bba.data_source_obj_id = " + dataSourceId
- + " AND bba.artifact_type_id = " + artifactTypeId
- + " AND attr.attribute_type_id = " + attributeTypeId;
-
- String errorMessage = "Unable to execute query to retrieve concatted attribute values.";
- String singleErrorMessage = "There was an error retrieving one of the results. That result will be omitted from concatted value.";
- String separator = ", ";
- return getConcattedStringsResult(query, valueParam, separator, errorMessage, singleErrorMessage);
- }
-
- private DataSourceDetailsSummary() {
- }
-}
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilities.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilities.java
deleted file mode 100644
index b72bc14330..0000000000
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilities.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Autopsy Forensic Browser
- *
- * Copyright 2019 - 2020 Basis Technology Corp.
- * Contact: carrier sleuthkit 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 java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.logging.Level;
-import org.sleuthkit.autopsy.coreutils.Logger;
-import org.sleuthkit.datamodel.SleuthkitCase;
-import org.sleuthkit.datamodel.TskCoreException;
-import org.apache.commons.lang.StringUtils;
-import org.sleuthkit.autopsy.casemodule.Case;
-import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
-import org.sleuthkit.datamodel.TskData;
-import org.sleuthkit.datamodel.DataSource;
-import org.sleuthkit.datamodel.TskData.TSK_FS_META_FLAG_ENUM;
-import org.sleuthkit.datamodel.TskData.TSK_FS_META_TYPE_ENUM;
-
-/**
- * Utilities for getting information about a data source or all data sources
- * from the case database.
- */
-final class DataSourceInfoUtilities {
-
- private static final Logger logger = Logger.getLogger(DataSourceInfoUtilities.class.getName());
-
- /**
- * Gets a count of tsk_files for a particular datasource where dir_type is
- * not a virtual directory and has a name.
- *
- * @param currentDataSource The datasource.
- * @param additionalWhere Additional sql where clauses.
- * @param onError The message to log on error.
- *
- * @return The count of files or null on error.
- */
- static Long getCountOfTskFiles(DataSource currentDataSource, String additionalWhere, String onError) {
- if (currentDataSource != null) {
- try {
- SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
- return skCase.countFilesWhere(
- "data_source_obj_id=" + currentDataSource.getId()
- + " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
- + " AND name<>''"
- + (StringUtils.isBlank(additionalWhere) ? "" : (" AND " + additionalWhere)));
- } catch (TskCoreException | NoCurrentCaseException ex) {
- logger.log(Level.WARNING, onError, ex);
- //unable to get count of files for the specified types cell will be displayed as empty
- }
- }
- return null;
- }
-
- /**
- * Gets a count of regular files for a particular datasource where the
- * dir_type and type are not a virtual directory and has a name.
- *
- * @param currentDataSource The datasource.
- * @param additionalWhere Additional sql where clauses.
- * @param onError The message to log on error.
- *
- * @return The count of files or null on error.
- */
- static Long getCountOfRegularFiles(DataSource currentDataSource, String additionalWhere, String onError) {
- String whereClause = "meta_type=" + TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue()
- + " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType();
-
- if (StringUtils.isNotBlank(additionalWhere)) {
- whereClause += " AND " + additionalWhere;
- }
-
- return getCountOfTskFiles(currentDataSource, whereClause, onError);
- }
-
- /**
- * An interface for handling a result set and returning a value.
- */
- interface ResultSetHandler {
-
- T process(ResultSet resultset) throws SQLException;
- }
-
- /**
- * Retrieves a result based on the provided query.
- *
- * @param query The query.
- * @param processor The result set handler.
- * @param errorMessage The error message to display if there is an error
- * retrieving the resultset.
- *
- * @return The ResultSetHandler value or null if no ResultSet could be
- * obtained.
- */
- static T getBaseQueryResult(String query, ResultSetHandler processor, String errorMessage) {
- try (SleuthkitCase.CaseDbQuery dbQuery = Case.getCurrentCaseThrows().getSleuthkitCase().executeQuery(query)) {
- ResultSet resultSet = dbQuery.getResultSet();
- try {
- return processor.process(resultSet);
- } catch (SQLException ex) {
- logger.log(Level.WARNING, errorMessage, ex);
- }
- } catch (TskCoreException | NoCurrentCaseException ex) {
- logger.log(Level.WARNING, errorMessage, ex);
- }
- return null;
- }
-
- /**
- * Creates sql where clause that does a bitwise check to see if flag is
- * present.
- *
- * @param flag The flag for which to check.
- *
- * @return The clause.
- */
- static String getMetaFlagsContainsStatement(TSK_FS_META_FLAG_ENUM flag) {
- return "meta_flags & " + flag.getValue() + " > 0";
- }
-
- /**
- * Empty private constructor
- */
- private DataSourceInfoUtilities() {
- }
-}
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceMimeTypeSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceMimeTypeSummary.java
deleted file mode 100644
index add28c0364..0000000000
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceMimeTypeSummary.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Autopsy Forensic Browser
- *
- * Copyright 2020 Basis Technology Corp.
- * Contact: carrier sleuthkit 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 java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-import org.sleuthkit.datamodel.DataSource;
-
-/**
- * Provides methods to query for datasource files by mime type.
- */
-public class DataSourceMimeTypeSummary {
-
- /**
- * Get the number of files in the case database for the current data source
- * which have the specified mimetypes.
- *
- * @param currentDataSource the data source which we are finding a file
- * count
- *
- * @param setOfMimeTypes the set of mime types which we are finding the
- * number of occurences of
- *
- * @return a Long value which represents the number of occurrences of the
- * specified mime types in the current case for the specified data
- * source, null if no count was retrieved
- */
- public static Long getCountOfFilesForMimeTypes(DataSource currentDataSource, Set setOfMimeTypes) {
- return DataSourceInfoUtilities.getCountOfRegularFiles(currentDataSource,
- "mime_type IN " + getSqlSet(setOfMimeTypes),
- "Unable to get count of files for specified mime types");
- }
-
- /**
- * Get the number of files in the case database for the current data source
- * which do not have the specified mimetypes.
- *
- * @param currentDataSource the data source which we are finding a file
- * count
- *
- * @param setOfMimeTypes the set of mime types that should be excluded.
- *
- * @return a Long value which represents the number of files that do not
- * have the specific mime type, but do have a mime type.
- */
- public static Long getCountOfFilesNotInMimeTypes(DataSource currentDataSource, Set setOfMimeTypes) {
- return DataSourceInfoUtilities.getCountOfRegularFiles(currentDataSource,
- "mime_type NOT IN " + getSqlSet(setOfMimeTypes)
- + " AND mime_type IS NOT NULL AND mime_type <> '' ",
- "Unable to get count of files without specified mime types");
- }
-
- /**
- * Gets the number of files in the data source with no assigned mime type.
- *
- * @param currentDataSource The data source.
- *
- * @return The number of files with no mime type or null if there is an
- * issue searching the data source.
- *
- */
- public static Long getCountOfFilesWithNoMimeType(DataSource currentDataSource) {
- return DataSourceInfoUtilities.getCountOfRegularFiles(currentDataSource,
- "(mime_type IS NULL OR mime_type = '') ",
- "Unable to get count of files without a mime type");
- }
-
- /**
- * Derives a sql set string (i.e. "('val1', 'val2', 'val3')"). A naive
- * attempt is made to sanitize the strings by removing single quotes from
- * values.
- *
- * @param setValues The values that should be present in the set. Single
- * quotes are removed.
- *
- * @return The sql set string.
- */
- private static String getSqlSet(Set setValues) {
- List quotedValues = setValues
- .stream()
- .map(str -> String.format("'%s'", str.replace("'", "")))
- .collect(Collectors.toList());
-
- String commaSeparatedQuoted = String.join(", ", quotedValues);
- return String.format("(%s) ", commaSeparatedQuoted);
- }
-
- private DataSourceMimeTypeSummary() {
- }
-}
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceTopProgramsSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceTopProgramsSummary.java
deleted file mode 100644
index 7c6927cd0d..0000000000
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceTopProgramsSummary.java
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Autopsy Forensic Browser
- *
- * Copyright 2020 Basis Technology Corp.
- * Contact: carrier sleuthkit 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 java.io.File;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.function.Function;
-import java.util.logging.Level;
-import java.util.stream.Collectors;
-import org.apache.commons.lang.StringUtils;
-import org.sleuthkit.autopsy.coreutils.Logger;
-import static org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceInfoUtilities.getBaseQueryResult;
-import org.sleuthkit.datamodel.BlackboardArtifact;
-import org.sleuthkit.datamodel.BlackboardAttribute;
-import org.sleuthkit.datamodel.DataSource;
-
-/**
- * Provides information to populate Top Programs Summary queries.
- */
-public class DataSourceTopProgramsSummary {
-
- private static final Logger logger = Logger.getLogger(DataSourceTopProgramsSummary.class.getName());
-
- /**
- * 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";
-
- /**
- * 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 clauses) {
- if (clauses.isEmpty()) {
- return "";
- }
-
- List 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 + "'";
- }
-
- /**
- * 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
- */
- public static List getTopPrograms(DataSource dataSource, int count) {
- 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";
-
- final String errorMessage = "Unable to get top program results; returning null.";
-
- DataSourceInfoUtilities.ResultSetHandler> handler = (resultSet) -> {
- List progResults = new ArrayList<>();
-
- boolean quitAtCount = false;
-
- while (resultSet.next() && (!quitAtCount || progResults.size() < count)) {
- try {
- 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));
-
- } catch (SQLException ex) {
- logger.log(Level.WARNING, "Failed to get a top program result from the result set.", ex);
- }
- }
-
- return progResults;
- };
-
- return getBaseQueryResult(query, handler, errorMessage);
- }
-
- /**
- * Functions that determine the folder name of a list of path elements. If
- * not matched, function returns null.
- */
- private static final List, 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;
- }
- );
-
- /**
- * Determines a short folder name if any. Otherwise, returns empty string.
- *
- * @param strPath The string path.
- *
- * @return The short folder name or empty string if not found.
- */
- public static String getShortFolderName(String strPath, String applicationName) {
- if (strPath == null) {
- return "";
- }
-
- List 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, String> matchEntry : SHORT_FOLDER_MATCHERS) {
- String result = matchEntry.apply(pathEls);
- if (StringUtils.isNotBlank(result)) {
- return result;
- }
- }
-
- return "";
- }
-
- private DataSourceTopProgramsSummary() {
- }
-}
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TopProgramsResult.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TopProgramsResult.java
deleted file mode 100644
index 7f682c3efb..0000000000
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TopProgramsResult.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Autopsy Forensic Browser
- *
- * Copyright 2020 Basis Technology Corp.
- * Contact: carrier sleuthkit 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 java.util.Date;
-
-/**
- * Describes a result of a program run on a datasource.
- */
-public 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;
- }
-}
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryCountsPanel.form b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryCountsPanel.form
deleted file mode 100644
index c9c1930787..0000000000
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryCountsPanel.form
+++ /dev/null
@@ -1,222 +0,0 @@
-
-
-
diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/FileTypePieChart.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/FileTypePieChart.java
deleted file mode 100644
index 691234cd48..0000000000
--- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/FileTypePieChart.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Autopsy Forensic Browser
- *
- * Copyright 2020 Basis Technology Corp.
- * Contact: carrier sleuthkit 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.ui;
-
-import java.awt.BorderLayout;
-import java.awt.Font;
-import javax.swing.JPanel;
-import org.sleuthkit.datamodel.DataSource;
-
-import org.jfree.chart.ChartFactory;
-import org.jfree.chart.ChartPanel;
-import org.jfree.chart.JFreeChart;
-import org.jfree.chart.labels.PieSectionLabelGenerator;
-import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
-import org.jfree.chart.plot.PiePlot;
-import org.jfree.data.general.DefaultPieDataset;
-
-import java.text.DecimalFormat;
-import java.util.Arrays;
-import java.util.Set;
-import java.util.stream.Collectors;
-import javax.swing.JLabel;
-import org.openide.util.NbBundle.Messages;
-import org.sleuthkit.autopsy.coreutils.FileTypeUtils;
-import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceMimeTypeSummary;
-import static org.sleuthkit.autopsy.coreutils.FileTypeUtils.FileTypeCategory;
-
-/**
- * A Pie Chart that shows file mime types in a data source.
- */
-class FileTypePieChart extends JPanel {
-
- private static final long serialVersionUID = 1L;
-
- private static final Font DEFAULT_FONT = new JLabel().getFont();
- private static final Font DEFAULT_HEADER_FONT = new Font(DEFAULT_FONT.getName(), DEFAULT_FONT.getStyle(), (int) (DEFAULT_FONT.getSize() * 1.5));
-
- private final DefaultPieDataset dataset = new DefaultPieDataset();
- private DataSource dataSource;
-
- // used for determining mime types that fall in the 'other' category
- private static final Set ALL_CATEGORY_MIME_TYPES = Arrays.asList(
- FileTypeCategory.IMAGE,
- FileTypeCategory.VIDEO,
- FileTypeCategory.AUDIO,
- FileTypeCategory.DOCUMENTS,
- FileTypeCategory.EXECUTABLE)
- .stream()
- .flatMap((cat) -> cat.getMediaTypes().stream())
- .collect(Collectors.toSet());
-
- /**
- * Default constructor for the pie chart.
- */
- @Messages({
- "DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type",
- "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.audio.row=Audio",
- "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.documents.row=Documents",
- "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.executables.row=Executables",
- "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.images.row=Images",
- "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.videos.row=Videos",
- "DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_other_label=Other",
- "DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_notAnalyzed_label=Not Analyzed"
- })
- FileTypePieChart() {
- // Create chart
- JFreeChart chart = ChartFactory.createPieChart(
- Bundle.DataSourceSummaryCountsPanel_byMimeTypeLabel_text(),
- dataset,
- true,
- true,
- false);
-
- chart.setBackgroundPaint(null);
- chart.getLegend().setItemFont(DEFAULT_FONT);
- chart.getTitle().setFont(DEFAULT_HEADER_FONT);
-
- PiePlot plot = ((PiePlot) chart.getPlot());
-
- //Format Label
- PieSectionLabelGenerator labelGenerator = new StandardPieSectionLabelGenerator(
- "{0}: {1} ({2})", new DecimalFormat("0"), new DecimalFormat("0.0%"));
-
- plot.setLabelGenerator(labelGenerator);
- plot.setLabelFont(DEFAULT_FONT);
-
- plot.setBackgroundPaint(null);
- plot.setOutlinePaint(null);
-
- // Create Panel
- ChartPanel panel = new ChartPanel(chart);
- this.setLayout(new BorderLayout());
- this.add(panel, BorderLayout.CENTER);
- }
-
- /**
- * The datasource currently used as the model with this pie chart.
- *
- * @return The datasource currently being used as the model in this pie
- * chart.
- */
- DataSource getDataSource() {
- return dataSource;
- }
-
- /**
- * Sets datasource to visualize in the pie chart.
- *
- * @param dataSource The datasource to use in this pie chart.
- */
- void setDataSource(DataSource dataSource) {
- this.dataSource = dataSource;
- this.dataset.clear();
-
- if (dataSource != null) {
- addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_images_row(),
- this.dataSource, FileTypeCategory.IMAGE);
- addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_videos_row(),
- this.dataSource, FileTypeCategory.VIDEO);
- addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_audio_row(),
- this.dataSource, FileTypeCategory.AUDIO);
- addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_documents_row(),
- this.dataSource, FileTypeCategory.DOCUMENTS);
- addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_executables_row(),
- this.dataSource, FileTypeCategory.EXECUTABLE);
- addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_other_label(),
- DataSourceMimeTypeSummary.getCountOfFilesNotInMimeTypes(this.dataSource, ALL_CATEGORY_MIME_TYPES));
- addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_notAnalyzed_label(),
- DataSourceMimeTypeSummary.getCountOfFilesWithNoMimeType(this.dataSource));
- }
- }
-
- /**
- * Adds count for file type category if there is a value. Uses fields
- * 'dataSource' and 'dataset'.
- *
- * @param label The label for this pie slice.
- * @param dataSource The data source.
- * @param category The category for the pie slice.
- */
- private void addIfPresent(String label, DataSource dataSource, FileTypeUtils.FileTypeCategory category) {
- if (dataSource == null) {
- return;
- }
-
- Long count = getCount(dataSource, category);
- addIfPresent(label, count);
- }
-
- /**
- * Adds count for a a label if the count is non-null and greater than 0.
- *
- * @param label The label.
- * @param count The count.
- */
- private void addIfPresent(String label, Long count) {
- if (count != null && count > 0) {
- this.dataset.setValue(label, count);
- }
- }
-
- /**
- * Retrieves the counts of files of a particular mime type for a particular
- * DataSource.
- *
- * @param dataSource The DataSource.
- * @param category The mime type category.
- *
- * @return The count.
- */
- private static Long getCount(DataSource dataSource, FileTypeUtils.FileTypeCategory category) {
- return DataSourceMimeTypeSummary.getCountOfFilesForMimeTypes(dataSource, category.getMediaTypes());
- }
-}
diff --git a/Core/src/org/sleuthkit/autopsy/resultviewers/summary/DataSourceSummaryResultViewer.java b/Core/src/org/sleuthkit/autopsy/resultviewers/summary/DataSourceSummaryResultViewer.java
index 4cc90e9843..1b1b3cb127 100644
--- a/Core/src/org/sleuthkit/autopsy/resultviewers/summary/DataSourceSummaryResultViewer.java
+++ b/Core/src/org/sleuthkit/autopsy/resultviewers/summary/DataSourceSummaryResultViewer.java
@@ -26,7 +26,7 @@ import org.openide.explorer.ExplorerManager;
import org.openide.nodes.Node;
import org.openide.util.NbBundle.Messages;
import org.openide.util.lookup.ServiceProvider;
-import org.sleuthkit.autopsy.datasourcesummary.ui.DataSourceSummaryTabbedPane;
+import org.sleuthkit.autopsy.casemodule.datasourcesummary.DataSourceSummaryTabbedPane;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
import org.sleuthkit.autopsy.corecomponents.AbstractDataResultViewer;
import org.sleuthkit.datamodel.DataSource;