diff --git a/bindings/java/doxygen/artifact_catalog.dox b/bindings/java/doxygen/artifact_catalog.dox index 8bf2fcb6997187159772dbd7070012e7dc56784d..e7db3f5d1b74229120a32bcb25728c89f53b3b2b 100644 --- a/bindings/java/doxygen/artifact_catalog.dox +++ b/bindings/java/doxygen/artifact_catalog.dox @@ -373,7 +373,7 @@ An email message found in an application file or database. - TSK_EMAIL_TO (Email addresses the email message was sent to, multiple emails should be in a comma separated string) - TSK_HEADERS (Transport message headers) - TSK_MSG_ID (Message ID supplied by the email application) -- TSK_PATH (Path in the data source to the file containing the email message) +- TSK_PATH (Path of email folders prefixed and separated by backslashes like '\Drafts\Work') - TSK_SUBJECT (Subject of the email message) - TSK_THREAD_ID (ID specified by the analysis module to group emails into threads for display purposes) diff --git a/bindings/java/src/org/sleuthkit/datamodel/Blackboard.java b/bindings/java/src/org/sleuthkit/datamodel/Blackboard.java index 1826e40793702e3b59858f4fb321fdbe79b86b5f..40360f7209611841183578d2d1b071cc3df3ffc0 100755 --- a/bindings/java/src/org/sleuthkit/datamodel/Blackboard.java +++ b/bindings/java/src/org/sleuthkit/datamodel/Blackboard.java @@ -443,10 +443,10 @@ public ArrayList<BlackboardAttribute> getBlackboardAttributes(final BlackboardAr CaseDbConnection connection = null; Statement statement = null; ResultSet rs = null; - + String rowId; switch (caseDb.getDatabaseType()) { - case POSTGRESQL: + case POSTGRESQL: rowId = "attrs.CTID"; break; case SQLITE: @@ -455,7 +455,7 @@ public ArrayList<BlackboardAttribute> getBlackboardAttributes(final BlackboardAr default: throw new TskCoreException("Unknown database type: " + caseDb.getDatabaseType()); } - + caseDb.acquireSingleUserCaseReadLock(); try { connection = caseDb.getConnection(); @@ -467,7 +467,7 @@ public ArrayList<BlackboardAttribute> getBlackboardAttributes(final BlackboardAr + "attrs.value_int64 AS value_int64, attrs.value_double AS value_double, " + "types.type_name AS type_name, types.display_name AS display_name " + "FROM blackboard_attributes AS attrs, blackboard_attribute_types AS types WHERE attrs.artifact_id = " + artifact.getArtifactID() - + " AND attrs.attribute_type_id = types.attribute_type_id " + + " AND attrs.attribute_type_id = types.attribute_type_id " + " ORDER BY " + rowId); ArrayList<BlackboardAttribute> attributes = new ArrayList<>(); while (rs.next()) { @@ -956,11 +956,14 @@ public Score deleteAnalysisResult(long artifactObjId, CaseDbTransaction transact */ private Score deleteAnalysisResult(AnalysisResult analysisResult, CaseDbTransaction transaction) throws TskCoreException { - try { + try { CaseDbConnection connection = transaction.getConnection(); + + // Delete the BlackboardArtifactTags for the analysisResult + caseDb.getTaggingManager().deleteBlackboardArtifactTags(analysisResult, transaction); // delete the blackboard artifacts row. This will also delete the tsk_analysis_result row - String deleteSQL = "DELETE FROM blackboard_artifacts WHERE artifact_obj_id = ?"; + String deleteSQL = "DELETE FROM tsk_objects WHERE obj_id = ?"; PreparedStatement deleteStatement = connection.getPreparedStatement(deleteSQL, Statement.RETURN_GENERATED_KEYS); deleteStatement.clearParameters(); @@ -978,6 +981,134 @@ private Score deleteAnalysisResult(AnalysisResult analysisResult, CaseDbTransact } } + /** + * Deletes all analysis results of certain type and (optionally) data + * source. + * + * @param type Type of analysis results to delete + * (BlackboardArtifact.Type) + * @param dataSourceId Data source ID to delete only analysis results from + * specific data source. If null, then delete analysis + * results from all data sources. + * + * @throws TskCoreException + */ + public void deleteAnalysisResults(BlackboardArtifact.Type type, Long dataSourceId) throws TskCoreException { + deleteAnalysisResults(type, dataSourceId, ""); + } + + /** + * Deletes all analysis results of certain type and (optionally) data + * source. + * + * @param type Type of analysis results to delete + * (BlackboardArtifact.Type) + * @param dataSourceId Data source ID to delete only analysis results from + * specific data source. If null, then delete analysis + * results from all data sources. + * @param configuration Name of the analysis result configuration to delete. + * Can be empty if there is no configuration for this + * analysis result type. + * + * @throws TskCoreException + */ + public void deleteAnalysisResults(BlackboardArtifact.Type type, Long dataSourceId, String configuration) throws TskCoreException { + + String dataSourceClause = dataSourceId == null + ? "" + : " AND artifacts.data_source_obj_id = ? "; // dataSourceId + + String configurationClause = (configuration == null || configuration.isEmpty() + ? " AND (configuration IS NULL OR configuration = '' )" + : " AND configuration = ? "); + + String getIdsQuery = "SELECT artifacts.artifact_obj_id AS artifact_obj_id, artifacts.obj_id AS obj_id, artifacts.data_source_obj_id AS data_source_obj_id " + + " FROM blackboard_artifacts artifacts " + + " JOIN blackboard_artifact_types AS types ON artifacts.artifact_type_id = types.artifact_type_id " + + " LEFT JOIN tsk_analysis_results AS results ON artifacts.artifact_obj_id = results.artifact_obj_id " + + " WHERE types.category_type = " + BlackboardArtifact.Category.ANALYSIS_RESULT.getID() + + " AND artifacts.artifact_type_id = ? " + + dataSourceClause + + configurationClause; + + List<Long> artifactObjIdsToDelete = new ArrayList<>(); + Map<Long, Long> objIdsToDsIds = new HashMap<>(); + CaseDbTransaction transaction = this.caseDb.beginTransaction(); + String currentQuery = ""; + try (CaseDbConnection connection = transaction.getConnection()) { + + try { + // get obj_ids of the artifacts that need to be deleted + currentQuery = getIdsQuery; + PreparedStatement preparedStatement = connection.getPreparedStatement(currentQuery, Statement.RETURN_GENERATED_KEYS); + preparedStatement.clearParameters(); + int paramIdx = 0; + + preparedStatement.setInt(++paramIdx, type.getTypeID()); + + if (dataSourceId != null) { + preparedStatement.setLong(++paramIdx, dataSourceId); + } + + if (!(configuration == null || configuration.isEmpty())) { + preparedStatement.setString(++paramIdx, configuration); + } + + try (ResultSet resultSet = connection.executeQuery(preparedStatement)) { + while (resultSet.next()) { + artifactObjIdsToDelete.add(resultSet.getLong("artifact_obj_id")); + + objIdsToDsIds.put(resultSet.getLong("obj_id"), resultSet.getLong("data_source_obj_id")); + } + } + + if (artifactObjIdsToDelete.isEmpty()) { + transaction.close(); + transaction = null; + return; + } + + // delete the identified artifacts by obj_id. the number of results + // could be very large so we should split deletion into batches to limit the + // size of the SQL string + int maxArtifactsToDeleteAtOnce = 50; + for (int startId = 0; startId < artifactObjIdsToDelete.size(); startId += maxArtifactsToDeleteAtOnce) { + + List<String> newList = artifactObjIdsToDelete.subList(startId, Math.min(artifactObjIdsToDelete.size(), startId + maxArtifactsToDeleteAtOnce)).stream() + .map(String::valueOf) + .collect(Collectors.toList()); + + currentQuery = "DELETE FROM tsk_objects WHERE obj_id IN (" + + String.join(",", newList) + + ")"; + + Statement statement = connection.createStatement(); + connection.executeUpdate(statement, currentQuery); + } + + for (Map.Entry<Long, Long> entry : objIdsToDsIds.entrySet()) { + Long objId = entry.getKey(); + Long dsId = entry.getValue(); + // register the deleted result with the transaction so an event can be fired for it. + transaction.registerDeletedAnalysisResult(objId); + + // update score of the source file + caseDb.getScoringManager().updateAggregateScoreAfterDeletion(objId, dsId, transaction); + } + + transaction.commit(); + transaction = null; + + } catch (SQLException ex) { + throw new TskCoreException(String.format("Error while performing query = '%s'", currentQuery), ex); + } + } finally { + if (transaction != null) { + transaction.rollback(); + } + } + } + private final static String ANALYSIS_RESULT_QUERY_STRING_GENERIC = "SELECT DISTINCT artifacts.artifact_id AS artifact_id, " //NON-NLS + " artifacts.obj_id AS obj_id, artifacts.artifact_obj_id AS artifact_obj_id, artifacts.data_source_obj_id AS data_source_obj_id, artifacts.artifact_type_id AS artifact_type_id, " + " types.type_name AS type_name, types.display_name AS display_name, types.category_type as category_type,"//NON-NLS @@ -1847,9 +1978,7 @@ public List<BlackboardArtifact> getExactMatchKeywordSearchResults(String keyword * well as the keyword. It should be empty for literal * exact match keyword search types. * @param searchType Type of keyword search query. - * @param kwsListName (Optional) Name of the keyword list for which the - * search results are for. If not specified, then the - * results will be for ad-hoc keyword searches. + * @param configuration Configuration of keyword hits. * @param dataSourceId (Optional) Data source id of the target data source. * If null, then the results will be for all data * sources. @@ -1859,15 +1988,18 @@ public List<BlackboardArtifact> getExactMatchKeywordSearchResults(String keyword * @throws TskCoreException If an exception is encountered while running * database query to obtain the keyword hits. */ - public List<BlackboardArtifact> getKeywordSearchResults(String keyword, String regex, TskData.KeywordSearchQueryType searchType, String kwsListName, Long dataSourceId) throws TskCoreException { - + @Beta + public List<BlackboardArtifact> getKeywordSearchResults(String keyword, String regex, TskData.KeywordSearchQueryType searchType, String configuration, Long dataSourceId) throws TskCoreException { + String dataSourceClause = dataSourceId == null ? "" : " AND artifacts.data_source_obj_id = ? "; // dataSourceId - String kwsListClause = (kwsListName == null || kwsListName.isEmpty() - ? " WHERE r.set_name IS NULL " - : " WHERE r.set_name = ? "); + // allow for current way configuration is used for keyword sets (i.e. configuration is list name) + // as well as previous way configuration was used for keyword sets (i.e. configuration was null or empty and TSK_SET_NAME was used) + String configurationClause = (configuration == null || configuration.isEmpty() + ? " WHERE ((r.configuration IS NULL OR LENGTH(r.configuration) = 0) AND (r.set_name IS NULL OR LENGTH(r.set_name) = 0))" + : " WHERE (r.configuration = ? OR ((r.configuration IS NULL OR LENGTH(r.configuration) = 0) AND r.set_name = ?))"); String keywordClause = (keyword == null || keyword.isEmpty() ? "" @@ -1912,7 +2044,7 @@ public List<BlackboardArtifact> getKeywordSearchResults(String keyword, String r + " WHERE types.category_type = " + BlackboardArtifact.Category.ANALYSIS_RESULT.getID() + " AND artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_KEYWORD_HIT.getTypeID() + " " + dataSourceClause + " ) r " - + kwsListClause + + configurationClause + keywordClause + searchTypeClause + regexClause; @@ -1928,9 +2060,10 @@ public List<BlackboardArtifact> getKeywordSearchResults(String keyword, String r if (dataSourceId != null) { preparedStatement.setLong(++paramIdx, dataSourceId); } - - if (!(kwsListName == null || kwsListName.isEmpty())) { - preparedStatement.setString(++paramIdx, kwsListName); + + if (!(configuration == null || configuration.isEmpty())) { + preparedStatement.setString(++paramIdx, configuration); + preparedStatement.setString(++paramIdx, configuration); } if (!(keyword == null || keyword.isEmpty())) { @@ -1944,7 +2077,7 @@ public List<BlackboardArtifact> getKeywordSearchResults(String keyword, String r if (!(regex == null || regex.isEmpty())) { preparedStatement.setString(++paramIdx, regex); } - + try (ResultSet resultSet = connection.executeQuery(preparedStatement)) { artifacts.addAll(resultSetToAnalysisResults(resultSet)); } @@ -1957,7 +2090,7 @@ public List<BlackboardArtifact> getKeywordSearchResults(String keyword, String r } return artifacts; } - + /** * Gets count of blackboard artifacts of given type that match a given WHERE * clause. Uses a SELECT COUNT(*) FROM blackboard_artifacts statement @@ -2335,7 +2468,7 @@ final public class ArtifactsPostedEvent { * artifacts are posted. Posted artifacts should be complete (all * attributes have been added) and ready for further analysis. * - * @param artifacts The artifacts. + * @param artifacts The artifacts. * @param moduleName The display name of the module posting the * artifacts. * @param ingestJobId The numeric identifier of the ingest job within diff --git a/bindings/java/src/org/sleuthkit/datamodel/BlackboardArtifact.java b/bindings/java/src/org/sleuthkit/datamodel/BlackboardArtifact.java index fba83e40ebd9c4d3d87817773af9ba14ae281ccd..b3990eb92e6f87470f3a4d7decf4a45ffa228aca 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/BlackboardArtifact.java +++ b/bindings/java/src/org/sleuthkit/datamodel/BlackboardArtifact.java @@ -900,21 +900,6 @@ public String toString() { return "BlackboardArtifact{" + "artifactID=" + artifactId + ", objID=" + getObjectID() + ", artifactObjID=" + artifactObjId + ", artifactTypeID=" + artifactTypeId + ", artifactTypeName=" + artifactTypeName + ", displayName=" + displayName + ", Case=" + getSleuthkitCase() + '}'; //NON-NLS } - /** - * Accepts a visitor SleuthkitItemVisitor that will perform an operation on - * this artifact type and return some object as the result of the operation. - * - * @param visitor The visitor, where the type parameter of the visitor is - * the type of the object that will be returned as the result - * of the visit operation. - * - * @return An object of type T. - */ - @Override - public <T> T accept(SleuthkitItemVisitor<T> visitor) { - return visitor.visit(this); - } - /** * Get the (reported) size of the content object. Artifact content is a * string dump of all its attributes. @@ -1594,7 +1579,7 @@ public int hashCode() { * http://sleuthkit.org/sleuthkit/docs/jni-docs/latest/artifact_catalog_page.html * for details on the standard attributes for each artifact type. */ - public enum ARTIFACT_TYPE implements SleuthkitVisitableItem { + public enum ARTIFACT_TYPE { /** * A generic information artifact. @@ -2116,23 +2101,6 @@ static public ARTIFACT_TYPE fromID(int id) { public String getDisplayName() { return displayName; } - - /** - * Accepts a visitor SleuthkitItemVisitor that will perform an operation - * on this artifact type and return some object as the result of the - * operation. - * - * @param visitor The visitor, where the type parameter of the visitor - * is the type of the object that will be returned as the - * result of the visit operation. - * - * @return An object of type T. - */ - @Override - public <T> T accept(SleuthkitItemVisitor<T> visitor) { - return visitor.visit(this); - } - } /** diff --git a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties-MERGED b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties-MERGED index f06ceeef19ac6743527a963603a4c5f418932bd2..9d168aa0b29391cf093bf4c4c152bf6de5e2be0a 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties-MERGED +++ b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties-MERGED @@ -394,6 +394,7 @@ OsAccountStatus.Unknown.text=Unknown OsAccountStatus.Active.text=Active OsAccountStatus.Disabled.text=Disabled OsAccountStatus.Deleted.text=Deleted +OsAccountStatus.NonExistent.text=Non Existent OsAccountType.Unknown.text=Unknown OsAccountType.Service.text=Service OsAccountType.Interactive.text=Interactive diff --git a/bindings/java/src/org/sleuthkit/datamodel/Content.java b/bindings/java/src/org/sleuthkit/datamodel/Content.java index 5993ac460165046abba1e0ec0cf1603f181e397a..a8779ad1e6cd6f8abb451e840e316f54c2fa0a6e 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/Content.java +++ b/bindings/java/src/org/sleuthkit/datamodel/Content.java @@ -30,7 +30,7 @@ * interface defines the basic methods for reading the content associated with * this object, the parent and children, and adding artifacts. */ -public interface Content extends SleuthkitVisitableItem { +public interface Content { /** * Reads data that this content object is associated with (file contents, diff --git a/bindings/java/src/org/sleuthkit/datamodel/ContentVisitor.java b/bindings/java/src/org/sleuthkit/datamodel/ContentVisitor.java index 7d922b9f126955745f0717dcdfcaccbde3728d71..875f9bad1345c4f950b256fee791e071e9f295d3 100755 --- a/bindings/java/src/org/sleuthkit/datamodel/ContentVisitor.java +++ b/bindings/java/src/org/sleuthkit/datamodel/ContentVisitor.java @@ -66,7 +66,7 @@ public interface ContentVisitor<T> { * @return result of the visit */ T visit(Image i); - + /** * Act on (visit) a Pool content object * @@ -74,7 +74,7 @@ public interface ContentVisitor<T> { * * @return result of the visit */ - T visit(Pool p); + T visit(Pool p); /** * Act on (visit) a Volume content object @@ -111,7 +111,7 @@ public interface ContentVisitor<T> { * @return result of the visit */ T visit(VirtualDirectory vd); - + /** * Act on (visit) a LocalDirectory content object * @@ -119,7 +119,7 @@ public interface ContentVisitor<T> { * * @return result of the visit */ - T visit(LocalDirectory ld); + T visit(LocalDirectory ld); /** * Act on (visit) a DerivedFile content object @@ -138,7 +138,7 @@ public interface ContentVisitor<T> { * @return result of the visit */ T visit(LocalFile df); - + /** * Act on (visit) a SlackFile content object * @@ -146,7 +146,7 @@ public interface ContentVisitor<T> { * * @return result of the visit */ - T visit(SlackFile sf); + T visit(SlackFile sf); /** * Act on (visit) a blackboard artifact object @@ -155,8 +155,17 @@ public interface ContentVisitor<T> { * * @return result of the visit */ - T visit(BlackboardArtifact ba); - + T visit(BlackboardArtifact ba); + + /** + * Act on (visit) a local files data source object + * + * @param ds The local files data source object + * + * @return result of the visit + */ + T visit(LocalFilesDataSource lfds); + /** * Act on (visit) a Report object * @@ -165,7 +174,7 @@ public interface ContentVisitor<T> { * @return result of the visit */ T visit(Report r); - + /** * Act on (visit) a OsAccount object * @@ -174,7 +183,7 @@ public interface ContentVisitor<T> { * @return result of the visit */ T visit(OsAccount act); - + /** * Act on (visit) an UnsupportedContent object * @@ -222,7 +231,7 @@ public T visit(Image i) { public T visit(Volume v) { return defaultVisit(v); } - + @Override public T visit(Pool p) { return defaultVisit(p); @@ -242,7 +251,7 @@ public T visit(LayoutFile lf) { public T visit(VirtualDirectory ld) { return defaultVisit(ld); } - + @Override public T visit(LocalDirectory ld) { return defaultVisit(ld); @@ -257,27 +266,32 @@ public T visit(DerivedFile df) { public T visit(LocalFile lf) { return defaultVisit(lf); } - + @Override public T visit(SlackFile sf) { return defaultVisit(sf); } - + @Override public T visit(BlackboardArtifact ba) { return defaultVisit(ba); } + @Override + public T visit(LocalFilesDataSource lfds) { + return defaultVisit(lfds); + } + @Override public T visit(Report r) { return defaultVisit(r); } - + @Override public T visit(OsAccount act) { return defaultVisit(act); } - + @Override public T visit(UnsupportedContent uc) { return defaultVisit(uc); diff --git a/bindings/java/src/org/sleuthkit/datamodel/DerivedFile.java b/bindings/java/src/org/sleuthkit/datamodel/DerivedFile.java index 22cbba2660f29ffbef4ac96d0afcfba3f42467d7..05676b3ed38bafdf194c08f569756c0bb228fdfb 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/DerivedFile.java +++ b/bindings/java/src/org/sleuthkit/datamodel/DerivedFile.java @@ -153,19 +153,6 @@ public synchronized DerivedMethod getDerivedMethod() throws TskCoreException { return derivedMethod; } - /** - * Accepts a content visitor (Visitor design pattern). - * - * @param visitor A ContentVisitor supplying an algorithm to run using this - * derived file as input. - * - * @return The output of the algorithm. - */ - @Override - public <T> T accept(SleuthkitItemVisitor<T> v) { - return v.visit(this); - } - /** * Accepts a Sleuthkit item visitor (Visitor design pattern). * diff --git a/bindings/java/src/org/sleuthkit/datamodel/Directory.java b/bindings/java/src/org/sleuthkit/datamodel/Directory.java index 877a626bedfc0912d9162d0afc215f78adc17e89..24612b577adc985b5bf14f08caaf3d4622215071 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/Directory.java +++ b/bindings/java/src/org/sleuthkit/datamodel/Directory.java @@ -97,19 +97,6 @@ public class Directory extends FsContent { super(db, objId, dataSourceObjectId, fsObjId, attrType, attrId, name, TskData.TSK_DB_FILES_TYPE_ENUM.FS, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, sha256Hash, sha1Hash, knownState, parentPath, null, null, ownerUid, osAccountObjId, TskData.CollectedStatus.UNKNOWN, Collections.emptyList()); } - /** - * Accepts a content visitor (Visitor design pattern). - * - * @param visitor A ContentVisitor supplying an algorithm to run using this - * directory as input. - * - * @return The output of the algorithm. - */ - @Override - public <T> T accept(SleuthkitItemVisitor<T> v) { - return v.visit(this); - } - /** * Accepts a Sleuthkit item visitor (Visitor design pattern). * diff --git a/bindings/java/src/org/sleuthkit/datamodel/File.java b/bindings/java/src/org/sleuthkit/datamodel/File.java index 5ee548df86a5a7532b83fb844328a8250e8b1af6..6fefc6ae807b11093d7e98865a6dfe60665a9d8c 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/File.java +++ b/bindings/java/src/org/sleuthkit/datamodel/File.java @@ -109,19 +109,6 @@ public class File extends FsContent { ownerUid, osAccountObjId, collected, fileAttributes); } - /** - * Accepts a content visitor (Visitor design pattern). - * - * @param visitor A ContentVisitor supplying an algorithm to run using this - * file as input. - * - * @return The output of the algorithm. - */ - @Override - public <T> T accept(SleuthkitItemVisitor<T> visitor) { - return visitor.visit(this); - } - /** * Accepts a Sleuthkit item visitor (Visitor design pattern). * diff --git a/bindings/java/src/org/sleuthkit/datamodel/FileSystem.java b/bindings/java/src/org/sleuthkit/datamodel/FileSystem.java index 45a21b58e30e55f5c554c47d6489f17eee56401a..646b09c9d44ce540e0488a3b97e29910b73a54d3 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/FileSystem.java +++ b/bindings/java/src/org/sleuthkit/datamodel/FileSystem.java @@ -208,11 +208,6 @@ public void finalize() throws Throwable { } } - @Override - public <T> T accept(SleuthkitItemVisitor<T> v) { - return v.visit(this); - } - @Override public <T> T accept(ContentVisitor<T> v) { return v.visit(this); diff --git a/bindings/java/src/org/sleuthkit/datamodel/HostAddress.java b/bindings/java/src/org/sleuthkit/datamodel/HostAddress.java index 4b545baee03e78c3acffffa4bc79432bcdafb160..191c759dec969d1b20ebac8b6b5a774471e77a01 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/HostAddress.java +++ b/bindings/java/src/org/sleuthkit/datamodel/HostAddress.java @@ -128,12 +128,6 @@ public <T> T accept(ContentVisitor<T> v) { throw new UnsupportedOperationException("Not supported yet."); } - @Override - public <T> T accept(SleuthkitItemVisitor<T> v) { - // TODO - throw new UnsupportedOperationException("Not supported yet."); - } - /** * A host may have different types of addresses at a given point in time. */ diff --git a/bindings/java/src/org/sleuthkit/datamodel/Image.java b/bindings/java/src/org/sleuthkit/datamodel/Image.java index f51eac30a399d09f063ceae1688eff564f1cb82d..8f1af1fe0cea9651f433b24f91547db795bc8ba7 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/Image.java +++ b/bindings/java/src/org/sleuthkit/datamodel/Image.java @@ -276,11 +276,6 @@ public String getTimeZone() { return timezone; } - @Override - public <T> T accept(SleuthkitItemVisitor<T> v) { - return v.visit(this); - } - @Override public <T> T accept(ContentVisitor<T> v) { return v.visit(this); diff --git a/bindings/java/src/org/sleuthkit/datamodel/LayoutFile.java b/bindings/java/src/org/sleuthkit/datamodel/LayoutFile.java index 938f57124be052ef9873731edc5365dfc1c53c8e..7a19041120f70a7f5f9768002ff39b8b246f5f14 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/LayoutFile.java +++ b/bindings/java/src/org/sleuthkit/datamodel/LayoutFile.java @@ -233,19 +233,6 @@ public <T> T accept(ContentVisitor<T> visitor) { return visitor.visit(this); } - /** - * Accepts a Sleuthkit item visitor (Visitor design pattern). - * - * @param visitor A SleuthkitItemVisitor supplying an algorithm to run using - * this file as input. - * - * @return The output of the algorithm. - */ - @Override - public <T> T accept(SleuthkitItemVisitor<T> visitor) { - return visitor.visit(this); - } - /** * Provides a string representation of this file. * diff --git a/bindings/java/src/org/sleuthkit/datamodel/LocalDirectory.java b/bindings/java/src/org/sleuthkit/datamodel/LocalDirectory.java index b3eed95ed10f0c91f772f87ce4016afe5cf61491..699f41de196d142ad2c325cfd084fc22a2cda69e 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/LocalDirectory.java +++ b/bindings/java/src/org/sleuthkit/datamodel/LocalDirectory.java @@ -112,19 +112,6 @@ public <T> T accept(ContentVisitor<T> visitor) { return visitor.visit(this); } - /** - * Accepts a Sleuthkit item visitor (Visitor design pattern). - * - * @param visitor A SleuthkitItemVisitor supplying an algorithm to run using - * this local directory as input. - * - * @return The output of the algorithm. - */ - @Override - public <T> T accept(SleuthkitItemVisitor<T> visitor) { - return visitor.visit(this); - } - /** * Provides a string representation of this local directory. * diff --git a/bindings/java/src/org/sleuthkit/datamodel/LocalFile.java b/bindings/java/src/org/sleuthkit/datamodel/LocalFile.java index 8a7948ce64ed12f7a9a9741a7ee5d2f5cfbd682b..8c22a2e25b45722fe228c5372aefb3d75dac25c5 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/LocalFile.java +++ b/bindings/java/src/org/sleuthkit/datamodel/LocalFile.java @@ -149,20 +149,6 @@ public <T> T accept(ContentVisitor<T> visitor) { return visitor.visit(this); } - /** - * Accepts a Sleuthkit item visitor (Visitor design pattern). - * - * @param <T> The type returned by the visitor. - * @param visitor A SleuthkitItemVisitor supplying an algorithm to run using - * this local file as input. - * - * @return The output of the algorithm. - */ - @Override - public <T> T accept(SleuthkitItemVisitor<T> visitor) { - return visitor.visit(this); - } - /** * Provides a string representation of this local file. * diff --git a/bindings/java/src/org/sleuthkit/datamodel/LocalFilesDataSource.java b/bindings/java/src/org/sleuthkit/datamodel/LocalFilesDataSource.java index 3107c4b7108a8220bcaabf59451fd3f6cf8a3839..ee172f188a107e8fdf2d0226c5934b9762d6f2d9 100755 --- a/bindings/java/src/org/sleuthkit/datamodel/LocalFilesDataSource.java +++ b/bindings/java/src/org/sleuthkit/datamodel/LocalFilesDataSource.java @@ -334,20 +334,6 @@ public <T> T accept(ContentVisitor<T> visitor) { return visitor.visit(this); } - /** - * Accepts a Sleuthkit item visitor (Visitor design pattern). - * - * @param <T> The type returned by the visitor. - * @param visitor A SleuthkitItemVisitor supplying an algorithm to run using - * this virtual directory as input. - * - * @return The output of the algorithm. - */ - @Override - public <T> T accept(SleuthkitItemVisitor<T> visitor) { - return visitor.visit(this); - } - /** * Constructs a local/logical files and/or directories data source. * diff --git a/bindings/java/src/org/sleuthkit/datamodel/OsAccount.java b/bindings/java/src/org/sleuthkit/datamodel/OsAccount.java index 3549228c49e287e24f8cbd2c3517a204eda73947..42f758a0e2addc4befb3d25a9ec7f2b568c678a2 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/OsAccount.java +++ b/bindings/java/src/org/sleuthkit/datamodel/OsAccount.java @@ -401,11 +401,6 @@ public <T> T accept(ContentVisitor<T> v) { throw new UnsupportedOperationException("Not supported yet."); } - @Override - public <T> T accept(SleuthkitItemVisitor<T> v) { - return v.visit(this); - } - /** * Abstracts attributes of an OS account. An attribute may be specific to a * host, or applicable across all hosts. diff --git a/bindings/java/src/org/sleuthkit/datamodel/Pool.java b/bindings/java/src/org/sleuthkit/datamodel/Pool.java index 98681759fd86791e7152ca2de1a0247113d7b737..9059f95bbcc88a87c20dca7fe166e74bf5197d16 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/Pool.java +++ b/bindings/java/src/org/sleuthkit/datamodel/Pool.java @@ -140,11 +140,6 @@ protected void finalize() throws Throwable { } } - @Override - public <T> T accept(SleuthkitItemVisitor<T> v) { - return v.visit(this); - } - @Override public <T> T accept(ContentVisitor<T> v) { return v.visit(this); diff --git a/bindings/java/src/org/sleuthkit/datamodel/Report.java b/bindings/java/src/org/sleuthkit/datamodel/Report.java index afc07dfacab807eb7cb53bf95444dc33279e396a..476cc3d1e2a0bbb89a9dbece2a849c6663838958 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/Report.java +++ b/bindings/java/src/org/sleuthkit/datamodel/Report.java @@ -404,9 +404,4 @@ public long getArtifactsCount(BlackboardArtifact.ARTIFACT_TYPE type) throws TskC public long getAllArtifactsCount() throws TskCoreException { return db.getBlackboardArtifactsCount(objectId); } - - @Override - public <T> T accept(SleuthkitItemVisitor<T> v) { - return v.visit(this); - } } diff --git a/bindings/java/src/org/sleuthkit/datamodel/ScoreChange.java b/bindings/java/src/org/sleuthkit/datamodel/ScoreChange.java index cf051b71dd02b7fef7840e4864eb37c8addee96c..4b8fe82ea36bcb5b57b4397ee778d5d511d13700 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/ScoreChange.java +++ b/bindings/java/src/org/sleuthkit/datamodel/ScoreChange.java @@ -18,8 +18,6 @@ */ package org.sleuthkit.datamodel; -import java.util.Optional; - /** * This class encapsulates a score change. */ diff --git a/bindings/java/src/org/sleuthkit/datamodel/SlackFile.java b/bindings/java/src/org/sleuthkit/datamodel/SlackFile.java index e6bf7c4e0d5c2ff98fc2efdaa90c9d08e5907630..e457191577171806c3f9223e86aafa69c1edcff8 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/SlackFile.java +++ b/bindings/java/src/org/sleuthkit/datamodel/SlackFile.java @@ -127,19 +127,6 @@ protected int readInt(byte[] buf, long offset, long len) throws TskCoreException return SleuthkitJNI.readFileSlack(fileHandle, buf, offset, len); } - /** - * Accepts a content visitor (Visitor design pattern). - * - * @param v A ContentVisitor supplying an algorithm to run using this file - * as input. - * - * @return The output of the algorithm. - */ - @Override - public <T> T accept(SleuthkitItemVisitor<T> v) { - return v.visit(this); - } - /** * Accepts a Sleuthkit item visitor (Visitor design pattern). * diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java index c04094367e8b6e2164ad3896bffb941361514893..d76f85de22ea6a8b8af4e45669868167a3a8d2de 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java +++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java @@ -11742,6 +11742,8 @@ public void deleteContentTag(ContentTag tag) throws TskCoreException { trans.commit(); trans = null; + + fireTSKEvent(new TskEvent.ContentTagsDeletedTskEvent(Collections.singletonList(tag))); } catch (SQLException ex) { throw new TskCoreException("Error deleting row from content_tags table (id = " + tag.getId() + ")", ex); } finally { @@ -12087,10 +12089,14 @@ public BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifac return taggingMgr.addArtifactTag(artifact, tagName, comment).getAddedTag(); } - /* + /** * Deletes a row from the blackboard_artifact_tags table in the case - * database. @param tag A BlackboardArtifactTag data transfer object (DTO) - * representing the row to delete. @throws TskCoreException + * database. + * + * @param tag A BlackboardArtifactTag data transfer object (DTO) + * representing the row to delete. + * + * @throws TskCoreException */ public void deleteBlackboardArtifactTag(BlackboardArtifactTag tag) throws TskCoreException { CaseDbTransaction trans = beginTransaction(); @@ -12111,6 +12117,9 @@ public void deleteBlackboardArtifactTag(BlackboardArtifactTag tag) throws TskCor trans.commit(); trans = null; + + fireTSKEvent(new TskEvent.BlackboardArtifactTagsDeletedTskEvent(Collections.singletonList(tag))); + } catch (SQLException ex) { throw new TskCoreException("Error deleting row from blackboard_artifact_tags table (id = " + tag.getId() + ")", ex); } finally { @@ -13963,6 +13972,7 @@ public static final class CaseDbTransaction { private List<Long> deletedOsAccountObjectIds = new ArrayList<>(); private List<Long> deletedResultObjectIds = new ArrayList<>(); + private List<BlackboardArtifactTag> deletedBlackboardArtifactTagIds = new ArrayList<>(); // Keep track of which threads have connections to debug deadlocks private static Set<Long> threadsWithOpenTransaction = new HashSet<>(); @@ -13982,7 +13992,6 @@ private CaseDbTransaction(SleuthkitCase sleuthkitCase) throws TskCoreException { sleuthkitCase.releaseSingleUserCaseWriteLock(); throw new TskCoreException("Failed to create transaction on case database", ex); } - } /** @@ -14076,6 +14085,16 @@ void registerMergedOsAccount(long sourceOsAccountObjId, long destinationOsAccoun void registerDeletedAnalysisResult(long analysisResultObjId) { this.deletedResultObjectIds.add(analysisResultObjId); } + + /** + * Saves a list of BlackboardArtifactTags that have been deleted as + * a parent of this transaction; + * + * @param tagIds Deleted tags. + */ + void registerDeletedBlackboardArtifactTags(List<BlackboardArtifactTag> tags) { + deletedBlackboardArtifactTagIds.addAll(tags); + } /** * Check if the given thread has an open transaction. @@ -14106,12 +14125,24 @@ public void commit() throws TskCoreException { close(); if (!scoreChangeMap.isEmpty()) { - Map<Long, List<ScoreChange>> changesByDataSource = scoreChangeMap.values().stream() - .collect(Collectors.groupingBy(ScoreChange::getDataSourceObjectId)); + // NOTE: data source ID can be NULL so we can't use Collectors.groupingBy(ScoreChange::getDataSourceObjectId) + // because that doesn't support NULL and throws an NPE + Map<Long, List<ScoreChange>> changesByDataSource = new HashMap<>(); + for (Map.Entry<Long, ScoreChange> entry : scoreChangeMap.entrySet()) { + List<ScoreChange> scoreChanges = changesByDataSource.get(entry.getValue().getDataSourceObjectId()); + if (scoreChanges == null) { + changesByDataSource.put(entry.getValue().getDataSourceObjectId(), new ArrayList<>(Arrays.asList(entry.getValue()))); + } else { + scoreChanges.add(entry.getValue()); + } + } for (Map.Entry<Long, List<ScoreChange>> entry : changesByDataSource.entrySet()) { sleuthkitCase.fireTSKEvent(new TskEvent.AggregateScoresChangedEvent(entry.getKey(), ImmutableSet.copyOf(entry.getValue()))); } } + if(!deletedBlackboardArtifactTagIds.isEmpty()) { + sleuthkitCase.fireTSKEvent(new TskEvent.BlackboardArtifactTagsDeletedTskEvent(deletedBlackboardArtifactTagIds)); + } if (!timelineEvents.isEmpty()) { for (TimelineEventAddedEvent evt : timelineEvents) { sleuthkitCase.fireTSKEvent(evt); diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitItemVisitor.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitItemVisitor.java deleted file mode 100644 index 5e90113f99b0647e451fb2d5cef4c80cca79a0b2..0000000000000000000000000000000000000000 --- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitItemVisitor.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Sleuth Kit Data Model - * - * Copyright 2011-2021 Basis Technology Corp. - * Contact: carrier <at> sleuthkit <dot> org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.datamodel; - -/** - * Interface for implementing a visitor pattern on all displayable items: - * Content implementations and blackboard artifacts. - * - * Visitor implements an algorithm on the content and blackboard artifacts - * objects. The algorithm is completely decoupled from the data object. The - * visitor pattern emulates double dispatch mechanism. It allows to act - * differently depending on the instance type, without need to test what the - * actual type is. E.g. it allows for processing an object hierarchy without - * using instanceof statements. Generic type parameter T is a return type from - * the visit methods. - * - * @param <T> return type of visit methods - */ -public interface SleuthkitItemVisitor<T> { - - /** - * Act on (visit) a Directory content object - * - * @param d the directory to visit / act on - * - * @return result of the visit - */ - T visit(Directory d); - - /** - * Act on (visit) a File content object - * - * @param f the file to visit / act on - * - * @return result of the visit - */ - T visit(File f); - - /** - * Act on (visit) a FileSystem content object - * - * @param fs the filesystem to visit / act on - * - * @return result of the visit - */ - T visit(FileSystem fs); - - /** - * Act on (visit) an Image content object - * - * @param i the image to visit / act on - * - * @return result of the visit - */ - T visit(Image i); - - /** - * Act on (visit) a Volume content object - * - * @param v the volume to visit / act on - * - * @return result of the visit - */ - T visit(Volume v); - - /** - * Act on (visit) a VolumeSystem content object - * - * @param vs the volume system to visit / act on - * - * @return result of the visit - */ - T visit(VolumeSystem vs); - - /** - * Act on (visit) a Pool content object - * - * @param pool the volume system to visit / act on - * - * @return result of the visit - */ - T visit(Pool pool); - - /** - * Act on (visit) a blackboard artifact object - * - * @param ba blackboard artifact object to visit / act on - * - * @return result of the visit - */ - T visit(BlackboardArtifact ba); - - /** - * Act on (visit) a blackboard artifact type - * - * @param tw blackboard artifact type to visit / act on - * - * @return result of the visit - */ - T visit(BlackboardArtifact.ARTIFACT_TYPE tw); - - /** - * Act on (visit) a layout file content object - * - * @param lf layout file to visit / act on - * - * @return result of the visit - */ - T visit(LayoutFile lf); - - /** - * Act on (visit) a VirtualDirectory content object - * - * @param ld layout dir to visit / act on - * - * @return result of the visit - */ - T visit(VirtualDirectory ld); - - /** - * Act on (visit) a LocalDirectory content object - * - * @param ld layout dir to visit / act on - * - * @return result of the visit - */ - T visit(LocalDirectory ld); - - /** - * Act on (visit) a DerivedFile content object - * - * @param df derived file to visit / act on - * - * @return result of the visit - */ - T visit(DerivedFile df); - - /** - * Act on (visit) a LocalFile content object - * - * @param lf local file to visit / act on - * - * @return result of the visit - */ - T visit(LocalFile lf); - - /** - * Act on (visit) a SlackFile content object - * - * @param sf slack file to visit / act on - * - * @return result of the visit - */ - T visit(SlackFile sf); - - /** - * Act on (visit) a Report content object - * - * @param report report to visit / act on - * - * @return result of the visit - */ - T visit(Report report); - - /** - * Act on (visit) a OsAccount content object - * - * @param account report to visit / act on - * - * @return result of the visit - */ - T visit(OsAccount account); - - /** - * Act on (visit) an UnsupportedContent object - * - * @param unsupportedContent content to visit / act on - * - * @return result of the visit - */ - T visit(UnsupportedContent unsupportedContent); - - /** - * Act on (visit) a LocalFilesDataSource content object - * - * @param localFilesDataSource report to visit / act on - * - * @return result of the visit - */ - T visit(LocalFilesDataSource localFilesDataSource); - - /** - * The default visitor - quickest method for implementing a custom visitor. - * Every visit method delegates to the defaultVisit method, the only - * required method to be implemented. Then, implement the specific visit - * methods for the objects on which the algorithm needs to act differently. - * - * @param <T> generic type, signifies the object type to be returned from - * visit() - */ - static abstract public class Default<T> implements SleuthkitItemVisitor<T> { - - protected abstract T defaultVisit(SleuthkitVisitableItem s); - - @Override - public T visit(Directory d) { - return defaultVisit(d); - } - - @Override - public T visit(File f) { - return defaultVisit(f); - } - - @Override - public T visit(FileSystem fs) { - return defaultVisit(fs); - } - - @Override - public T visit(Image i) { - return defaultVisit(i); - } - - @Override - public T visit(Volume v) { - return defaultVisit(v); - } - - @Override - public T visit(VolumeSystem vs) { - return defaultVisit(vs); - } - - @Override - public T visit(Pool p) { - return defaultVisit(p); - } - - @Override - public T visit(BlackboardArtifact ba) { - return defaultVisit(ba); - } - - @Override - public T visit(BlackboardArtifact.ARTIFACT_TYPE tw) { - return defaultVisit(tw); - } - - @Override - public T visit(LayoutFile lf) { - return defaultVisit(lf); - } - - @Override - public T visit(VirtualDirectory vd) { - return defaultVisit(vd); - } - - @Override - public T visit(LocalDirectory ld) { - return defaultVisit(ld); - } - - @Override - public T visit(DerivedFile df) { - return defaultVisit(df); - } - - @Override - public T visit(LocalFile lf) { - return defaultVisit(lf); - } - - @Override - public T visit(SlackFile sf) { - return defaultVisit(sf); - } - - @Override - public T visit(Report report) { - return defaultVisit(report); - } - - @Override - public T visit(OsAccount account) { - return defaultVisit(account); - } - - @Override - public T visit(UnsupportedContent unsupportedContent) { - return defaultVisit(unsupportedContent); - } - - @Override - public T visit(LocalFilesDataSource localFilesDataSource) { - return defaultVisit(localFilesDataSource); - } - } -} diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitVisitableItem.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitVisitableItem.java deleted file mode 100644 index ed17d61d71d567db2bea40745c95888fceaf41e0..0000000000000000000000000000000000000000 --- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitVisitableItem.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Sleuth Kit Data Model - * - * Copyright 2011 Basis Technology Corp. - * Contact: carrier <at> sleuthkit <dot> org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.datamodel; - -/** - * Interface for all visitable datatypes that can be found in the tsk database - */ -public interface SleuthkitVisitableItem { - - /** - * visitor pattern support - * - * @param v visitor - * - * @return visitor return value - */ - public <T> T accept(SleuthkitItemVisitor<T> v); - -} diff --git a/bindings/java/src/org/sleuthkit/datamodel/TaggingManager.java b/bindings/java/src/org/sleuthkit/datamodel/TaggingManager.java index 58cf8d2001274dfff169c73bcc6fa4268d1e4f47..b63b88f4e4f778dd41decaf6387c1e94114bca74 100755 --- a/bindings/java/src/org/sleuthkit/datamodel/TaggingManager.java +++ b/bindings/java/src/org/sleuthkit/datamodel/TaggingManager.java @@ -26,6 +26,7 @@ import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import org.sleuthkit.datamodel.SleuthkitCase.CaseDbConnection; import org.sleuthkit.datamodel.SleuthkitCase.CaseDbTransaction; import static org.sleuthkit.datamodel.TskData.DbType.POSTGRESQL; @@ -271,7 +272,7 @@ public BlackboardArtifactTagChange addArtifactTag(BlackboardArtifact artifact, T CaseDbTransaction trans = null; try { // If a TagName is part of a TagSet remove any existing tags from the - // set that are currenctly on the artifact + // set that are currently on the artifact long tagSetId = tagName.getTagSetId(); if (tagSetId > 0) { // Get the list of all of the blackboardArtifactTags that use @@ -348,6 +349,10 @@ public BlackboardArtifactTagChange addArtifactTag(BlackboardArtifact artifact, T trans.commit(); + skCase.fireTSKEvent(new TskEvent.BlackboardArtifactTagsDeletedTskEvent(removedTags)); + + skCase.fireTSKEvent(new TskEvent.BlackboardArtifactTagsAddedTskEvent(Collections.singletonList(artifactTag))); + return new BlackboardArtifactTagChange(artifactTag, removedTags); } catch (SQLException ex) { if (trans != null) { @@ -516,6 +521,10 @@ public ContentTagChange addContentTag(Content content, TagName tagName, String c content.getId(), dataSourceId, getTagScore(tagName.getKnownStatus()), trans); trans.commit(); + + skCase.fireTSKEvent(new TskEvent.ContentTagsDeletedTskEvent(Collections.singletonList(contentTag))); + skCase.fireTSKEvent(new TskEvent.ContentTagsAddedTskEvent(Collections.singletonList(contentTag))); + return new ContentTagChange(contentTag, removedTags); } catch (SQLException ex) { trans.rollback(); @@ -698,6 +707,44 @@ private List<TagName> getTagNamesByTagSetID(int tagSetId) throws TskCoreExceptio return tagNameList; } + + /** + * Delete any BlackboardArtifactTags (Result Tag) associated with the given + * artifact. + * + * @param artifact + * @param transaction + * + * @throws TskCoreException + */ + public void deleteBlackboardArtifactTags(BlackboardArtifact artifact, CaseDbTransaction transaction) throws TskCoreException { + List<BlackboardArtifactTag> tags = skCase.getBlackboardArtifactTagsByArtifact(artifact); + if (tags.isEmpty()) { + return; + } + + List<Long> tagIds = new ArrayList<>(); + for (BlackboardArtifactTag tag : tags) { + tagIds.add(tag.getId()); + } + + String query = String.format("DELETE FROM blackboard_artifact_tags WHERE tag_id IN (%s)", + tagIds.stream(). + map(String::valueOf) + .collect(Collectors.joining(","))); + + CaseDbConnection connection = transaction.getConnection(); + + try (Statement statement = connection.createStatement()) { + statement.executeUpdate(query); + } catch (SQLException ex) { + throw new TskCoreException("Error deleting row from blackboard_artifact_tags table (ids = " + tagIds.stream(). + map(String::valueOf) + .collect(Collectors.joining(",")) + ")", ex); + } + + transaction.registerDeletedBlackboardArtifactTags(tags); + } /** * Object to store the tag change from a call to addArtifactTag. diff --git a/bindings/java/src/org/sleuthkit/datamodel/TskEvent.java b/bindings/java/src/org/sleuthkit/datamodel/TskEvent.java index 723a7bfff7b4c8ddd686077fa5a25e7ecb35506a..da6842036cf6546fc219e4eea2c2a24587b9ff7c 100755 --- a/bindings/java/src/org/sleuthkit/datamodel/TskEvent.java +++ b/bindings/java/src/org/sleuthkit/datamodel/TskEvent.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.Optional; /** @@ -92,7 +93,7 @@ public final static class AggregateScoresChangedEvent extends TskObjectsEvent<Sc super(scoreChanges.asList()); this.dataSourceObjectId = dataSourceObjectId; scoreChanges.stream().forEach(chg -> { - if (!chg.getDataSourceObjectId().equals(dataSourceObjectId)) { + if (!Objects.equals(chg.getDataSourceObjectId(), dataSourceObjectId)) { throw new IllegalArgumentException("All data source object IDs in List<ScoreChange> must match dataSourceObjectId"); } }); @@ -669,4 +670,105 @@ public List<Long> getTagSetIds() { return getDataModelObjects(); } } + + /** + * Class for BlackboardArtifactTag (Result Tag) events. + */ + static final class BlackboardArtifactTagsAddedTskEvent extends TskObjectsEvent<BlackboardArtifactTag> { + + /** + * Constructs the BlackboardArtifactTag event. + * + * @param tags The BlackboardArtifactTag that are the subjects of the + * event. + */ + BlackboardArtifactTagsAddedTskEvent(List<BlackboardArtifactTag> tags) { + super(tags); + } + + /** + * Gets the tags. + * + * @return The tags. + */ + public List<BlackboardArtifactTag> getTags() { + return getDataModelObjects(); + } + + } + + /** + * An event published when one or more BlackboardArtifactTag (Result Tag) + * have been deleted. + */ + public final static class BlackboardArtifactTagsDeletedTskEvent extends TskObjectsEvent<BlackboardArtifactTag> { + + /** + * Constructs a deleted event for one or more BlackboardArtifactTag. + * + * @param tags The ids of the deleted tags. + */ + public BlackboardArtifactTagsDeletedTskEvent(List<BlackboardArtifactTag> tags) { + super(tags); + } + + /** + * Returns the list of deleted TagSet ids. + * + * @return The list of deleted tag ids. + */ + public List<BlackboardArtifactTag> getTags() { + return getDataModelObjects(); + } + } + + /** + * Class for BlackboardArtifactTag (File Tag) events. + */ + static class ContentTagsAddedTskEvent extends TskObjectsEvent<ContentTag> { + + /** + * Constructs the ContentTag event. + * + * @param tags The ContentTag that are the subjects of the event. + */ + ContentTagsAddedTskEvent(List<ContentTag> tags) { + super(tags); + } + + /** + * Gets the tags. + * + * @return The tags. + */ + public List<ContentTag> getTags() { + return getDataModelObjects(); + } + + } + + /** + * An event published when one or more ContentTags (File Tag) have been + * deleted. + */ + public final static class ContentTagsDeletedTskEvent extends TskObjectsEvent<ContentTag> { + + /** + * Constructs a deleted event for one or more ContentTag. + * + * @param tags The deleted tags. + */ + public ContentTagsDeletedTskEvent(List<ContentTag> tags) { + super(tags); + } + + /** + * Returns the list of deleted ContentTags. + * + * @return The list of deleted tag ids. + */ + public List<ContentTag> getTags() { + return getDataModelObjects(); + } + } } diff --git a/bindings/java/src/org/sleuthkit/datamodel/UnsupportedContent.java b/bindings/java/src/org/sleuthkit/datamodel/UnsupportedContent.java index d9bbca1bdd7b59ada02ad29b51d762789b4ceedd..120a4988c75a89cf8d11476501c3338585c40492 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/UnsupportedContent.java +++ b/bindings/java/src/org/sleuthkit/datamodel/UnsupportedContent.java @@ -55,9 +55,4 @@ public long getSize() { public <T> T accept(ContentVisitor<T> v) { return v.visit(this); } - - @Override - public <T> T accept(SleuthkitItemVisitor<T> v) { - return v.visit(this); - } } diff --git a/bindings/java/src/org/sleuthkit/datamodel/VirtualDirectory.java b/bindings/java/src/org/sleuthkit/datamodel/VirtualDirectory.java index df34ec23bca9df59956859758828afc36c3b9b56..a349e623ab4d8e8581856655f2d224a25bd9444e 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/VirtualDirectory.java +++ b/bindings/java/src/org/sleuthkit/datamodel/VirtualDirectory.java @@ -120,20 +120,6 @@ public <T> T accept(ContentVisitor<T> visitor) { return visitor.visit(this); } - /** - * Accepts a Sleuthkit item visitor (Visitor design pattern). - * - * @param <T> The type returned by the visitor. - * @param visitor A SleuthkitItemVisitor supplying an algorithm to run using - * this virtual directory as input. - * - * @return The output of the algorithm. - */ - @Override - public <T> T accept(SleuthkitItemVisitor<T> visitor) { - return visitor.visit(this); - } - /** * Provides a string representation of this virtual directory. * diff --git a/bindings/java/src/org/sleuthkit/datamodel/Volume.java b/bindings/java/src/org/sleuthkit/datamodel/Volume.java index 48df129195736a44c39f573bf76cf93cadcaf796..2b10c357ad7571f768328e2e2a48eb3522f440c0 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/Volume.java +++ b/bindings/java/src/org/sleuthkit/datamodel/Volume.java @@ -256,11 +256,6 @@ public static String vsFlagToString(long vsFlag) { return result; } - @Override - public <T> T accept(SleuthkitItemVisitor<T> v) { - return v.visit(this); - } - @Override public <T> T accept(ContentVisitor<T> v) { return v.visit(this); diff --git a/bindings/java/src/org/sleuthkit/datamodel/VolumeSystem.java b/bindings/java/src/org/sleuthkit/datamodel/VolumeSystem.java index acb315595c333cce4947c39bfcf56e6e05e28913..00154ab49f3c79e554dca36e6da366bb89f30fab 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/VolumeSystem.java +++ b/bindings/java/src/org/sleuthkit/datamodel/VolumeSystem.java @@ -132,11 +132,6 @@ public void finalize() throws Throwable { super.finalize(); } } - - @Override - public <T> T accept(SleuthkitItemVisitor<T> v) { - return v.visit(this); - } @Override public <T> T accept(ContentVisitor<T> v) {