53public final class Blackboard {
55 private static final Logger LOGGER = Logger.getLogger(Blackboard.class.getName());
69 static final int MIN_USER_DEFINED_TYPE_ID = 10000;
80 this.caseDb = Objects.requireNonNull(casedb,
"Cannot create Blackboard for null SleuthkitCase");
100 postArtifacts(Collections.singleton(artifact), moduleName,
null);
139 postArtifacts(Collections.singleton(artifact), moduleName, ingestJobId);
160 caseDb.getTimelineManager().addArtifactEvents(artifact);
162 throw new BlackboardException(String.format(
"Failed to add events to timeline for artifact '%s'", artifact), ex);
200 if (category ==
null) {
204 if (typeNameToArtifactTypeMap.containsKey(typeName)) {
205 return typeNameToArtifactTypeMap.get(typeName);
210 trans = caseDb.beginTransaction();
212 CaseDbConnection connection = trans.getConnection();
216 try (PreparedStatement findCurrPrepState = connection.prepareStatement(
217 "SELECT artifact_type_id FROM blackboard_artifact_types WHERE type_name = ?",
218 Statement.RETURN_GENERATED_KEYS)) {
219 findCurrPrepState.setString(1, typeName);
221 try (ResultSet rs = connection.executeQuery(findCurrPrepState)) {
222 typeFound = rs.next();
229 try (Statement getNextIdState = connection.createStatement();
230 ResultSet rs = connection.executeQuery(getNextIdState,
231 "SELECT MAX(artifact_type_id) AS highest_id FROM blackboard_artifact_types")) {
233 maxID = rs.getInt(
"highest_id");
234 if (maxID < MIN_USER_DEFINED_TYPE_ID) {
235 maxID = MIN_USER_DEFINED_TYPE_ID;
243 try (PreparedStatement insertItemPrepState = connection.prepareStatement(
244 "INSERT INTO blackboard_artifact_types (artifact_type_id, type_name, display_name, category_type) VALUES (?, ?, ?, ?)",
245 Statement.RETURN_GENERATED_KEYS)) {
246 insertItemPrepState.setInt(1, maxID);
247 insertItemPrepState.setString(2, typeName);
248 insertItemPrepState.setString(3, displayName);
249 insertItemPrepState.setInt(4, category.getID());
251 insertItemPrepState.executeUpdate();
257 this.typeIdToArtifactTypeMap.put(type.getTypeID(), type);
258 this.typeNameToArtifactTypeMap.put(type.getTypeName(), type);
279 LOGGER.log(Level.SEVERE,
"Error rolling back transaction", ex2);
304 if (this.typeNameToAttributeTypeMap.containsKey(attrTypeName)) {
305 return this.typeNameToAttributeTypeMap.get(attrTypeName);
307 CaseDbConnection connection =
null;
310 caseDb.acquireSingleUserCaseReadLock();
312 connection = caseDb.getConnection();
313 s = connection.createStatement();
314 rs = connection.executeQuery(s,
"SELECT attribute_type_id, type_name, display_name, value_type FROM blackboard_attribute_types WHERE type_name = '" + attrTypeName +
"'");
319 this.typeIdToAttributeTypeMap.put(type.getTypeID(), type);
320 this.typeNameToAttributeTypeMap.put(attrTypeName, type);
323 }
catch (SQLException ex) {
328 closeConnection(connection);
329 caseDb.releaseSingleUserCaseReadLock();
344 if (this.typeIdToAttributeTypeMap.containsKey(typeID)) {
345 return this.typeIdToAttributeTypeMap.get(typeID);
347 CaseDbConnection connection =
null;
352 connection = caseDb.getConnection();
353 s = connection.createStatement();
354 rs = connection.executeQuery(s,
"SELECT attribute_type_id, type_name, display_name, value_type FROM blackboard_attribute_types WHERE attribute_type_id = " + typeID +
"");
355 BlackboardAttribute.Type type =
null;
357 type =
new BlackboardAttribute.Type(rs.getInt(
"attribute_type_id"), rs.getString(
"type_name"),
358 rs.getString(
"display_name"), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromType(rs.getLong(
"value_type")));
359 this.typeIdToAttributeTypeMap.put(typeID, type);
360 this.typeNameToAttributeTypeMap.put(type.getTypeName(), type);
363 }
catch (SQLException ex) {
364 throw new TskCoreException(
"Error getting attribute type id", ex);
368 closeConnection(connection);
369 caseDb.releaseSingleUserCaseReadLock();
384 if (this.typeNameToArtifactTypeMap.containsKey(artTypeName)) {
385 return this.typeNameToArtifactTypeMap.get(artTypeName);
388 caseDb.acquireSingleUserCaseReadLock();
389 try (CaseDbConnection connection = caseDb.getConnection(); PreparedStatement getTypePrepState = connection.prepareStatement(
390 "SELECT artifact_type_id, type_name, display_name, category_type FROM blackboard_artifact_types WHERE type_name = ?",
391 Statement.RETURN_GENERATED_KEYS)) {
392 getTypePrepState.setString(1, artTypeName);
394 try (ResultSet rs = getTypePrepState.executeQuery()) {
398 rs.getString(
"type_name"), rs.getString(
"display_name"),
400 this.typeIdToArtifactTypeMap.put(type.getTypeID(), type);
401 this.typeNameToArtifactTypeMap.put(artTypeName, type);
405 }
catch (SQLException ex) {
406 throw new TskCoreException(
"Error getting artifact type from the database", ex);
408 caseDb.releaseSingleUserCaseReadLock();
424 if (this.typeIdToArtifactTypeMap.containsKey(artTypeId)) {
425 return typeIdToArtifactTypeMap.get(artTypeId);
427 CaseDbConnection connection =
null;
430 caseDb.acquireSingleUserCaseReadLock();
432 connection = caseDb.getConnection();
433 s = connection.createStatement();
434 rs = connection.executeQuery(s,
"SELECT artifact_type_id, type_name, display_name, category_type FROM blackboard_artifact_types WHERE artifact_type_id = " + artTypeId +
"");
438 rs.getString(
"type_name"), rs.getString(
"display_name"),
440 this.typeIdToArtifactTypeMap.put(artTypeId, type);
441 this.typeNameToArtifactTypeMap.put(type.getTypeName(), type);
444 throw new TskCoreException(
"No artifact type found matching id: " + artTypeId);
446 }
catch (SQLException ex) {
447 throw new TskCoreException(
"Error getting artifact type from the database", ex);
451 closeConnection(connection);
452 caseDb.releaseSingleUserCaseReadLock();
466 CaseDbConnection connection =
null;
467 Statement statement =
null;
471 switch (caseDb.getDatabaseType()) {
473 rowId =
"attrs.CTID";
476 rowId =
"attrs.ROWID";
479 throw new TskCoreException(
"Unknown database type: " + caseDb.getDatabaseType());
482 caseDb.acquireSingleUserCaseReadLock();
484 connection = caseDb.getConnection();
485 statement = connection.createStatement();
486 rs = connection.executeQuery(statement,
"SELECT attrs.artifact_id AS artifact_id, "
487 +
"attrs.source AS source, attrs.context AS context, attrs.attribute_type_id AS attribute_type_id, "
488 +
"attrs.value_type AS value_type, attrs.value_byte AS value_byte, "
489 +
"attrs.value_text AS value_text, attrs.value_int32 AS value_int32, "
490 +
"attrs.value_int64 AS value_int64, attrs.value_double AS value_double, "
491 +
"types.type_name AS type_name, types.display_name AS display_name "
492 +
"FROM blackboard_attributes AS attrs, blackboard_attribute_types AS types WHERE attrs.artifact_id = " + artifact.getArtifactID()
493 +
" AND attrs.attribute_type_id = types.attribute_type_id "
494 +
" ORDER BY " + rowId);
495 ArrayList<BlackboardAttribute> attributes =
new ArrayList<>();
498 attr.setParentDataSourceID(artifact.getDataSourceObjectID());
499 attributes.add(attr);
502 }
catch (SQLException ex) {
503 throw new TskCoreException(
"Error getting attributes for artifact, artifact id = " + artifact.getArtifactID(), ex);
506 closeStatement(statement);
507 closeConnection(connection);
508 caseDb.releaseSingleUserCaseReadLock();
523 public <T extends BlackboardArtifact>
void loadBlackboardAttributes(List<T> arts)
throws TskCoreException {
525 if (arts.isEmpty()) {
530 Map<Long, BlackboardArtifact> artifactMap =
new HashMap<>();
531 for (BlackboardArtifact art : arts) {
532 artifactMap.put(art.getArtifactID(), art);
536 Map<Long, List<BlackboardAttribute>> attributeMap =
new HashMap<>();
539 String idString = arts.stream().map(p -> Long.toString(p.getArtifactID())).collect(Collectors.joining(
", "));
544 rowId =
"attrs.CTID";
547 rowId =
"attrs.ROWID";
550 throw new TskCoreException(
"Unknown database type: " + caseDb.
getDatabaseType());
554 CaseDbConnection connection =
null;
555 Statement statement =
null;
559 connection = caseDb.getConnection();
560 statement = connection.createStatement();
561 rs = connection.executeQuery(statement,
"SELECT attrs.artifact_id AS artifact_id, "
562 +
"attrs.source AS source, attrs.context AS context, attrs.attribute_type_id AS attribute_type_id, "
563 +
"attrs.value_type AS value_type, attrs.value_byte AS value_byte, "
564 +
"attrs.value_text AS value_text, attrs.value_int32 AS value_int32, "
565 +
"attrs.value_int64 AS value_int64, attrs.value_double AS value_double, "
566 +
"types.type_name AS type_name, types.display_name AS display_name "
567 +
"FROM blackboard_attributes AS attrs, blackboard_attribute_types AS types WHERE attrs.artifact_id IN (" + idString +
") "
568 +
" AND attrs.attribute_type_id = types.attribute_type_id"
569 +
" ORDER BY " + rowId);
571 final BlackboardAttribute attr = createAttributeFromResultSet(rs);
572 attr.setParentDataSourceID(artifactMap.get(attr.getArtifactID()).getDataSourceObjectID());
575 if (!attributeMap.containsKey(attr.getArtifactID())) {
576 attributeMap.put(attr.getArtifactID(),
new ArrayList<>());
578 attributeMap.get(attr.getArtifactID()).add(attr);
582 for (Long artifactID : attributeMap.keySet()) {
583 artifactMap.get(artifactID).setAttributes(attributeMap.get(artifactID));
586 }
catch (SQLException ex) {
587 throw new TskCoreException(
"Error loading attributes", ex);
590 closeStatement(statement);
591 closeConnection(connection);
592 caseDb.releaseSingleUserCaseReadLock();
604 private BlackboardAttribute createAttributeFromResultSet(ResultSet rs)
throws SQLException {
605 int attributeTypeId = rs.getInt(
"attribute_type_id");
606 String attributeTypeName = rs.getString(
"type_name");
607 BlackboardAttribute.Type attributeType;
608 if (this.typeIdToAttributeTypeMap.containsKey(attributeTypeId)) {
609 attributeType = this.typeIdToAttributeTypeMap.get(attributeTypeId);
611 attributeType =
new BlackboardAttribute.Type(attributeTypeId, attributeTypeName,
612 rs.getString(
"display_name"),
613 BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromType(rs.getInt(
"value_type")));
614 this.typeIdToAttributeTypeMap.put(attributeTypeId, attributeType);
615 this.typeNameToAttributeTypeMap.put(attributeTypeName, attributeType);
618 return new BlackboardAttribute(
619 rs.getLong(
"artifact_id"),
621 rs.getString(
"source"),
622 rs.getString(
"context"),
623 rs.getInt(
"value_int32"),
624 rs.getLong(
"value_int64"),
625 rs.getDouble(
"value_double"),
626 rs.getString(
"value_text"),
627 rs.getBytes(
"value_byte"), caseDb
643 caseDb.acquireSingleUserCaseWriteLock();
644 try (CaseDbConnection connection = caseDb.getConnection()) {
646 String updateString =
"UPDATE tsk_file_attributes SET value_byte = ?, value_text = ?, value_int32 = ?, "
647 +
" value_int64 = ?, value_double = ? WHERE attribute_type_id = " + attr.getAttributeType().getTypeID()
648 +
" AND obj_id = " + fileObjId;
650 try (PreparedStatement preparedStatement = connection.getPreparedStatement(updateString, Statement.NO_GENERATED_KEYS);) {
651 preparedStatement.clearParameters();
654 preparedStatement.setBytes(1, attr.getValueBytes());
656 preparedStatement.setBytes(1,
null);
661 preparedStatement.setString(2, attr.getValueString());
663 preparedStatement.setString(2,
null);
667 preparedStatement.setInt(3, attr.getValueInt());
669 preparedStatement.setNull(3, java.sql.Types.INTEGER);
674 preparedStatement.setLong(4, attr.getValueLong());
676 preparedStatement.setNull(4, java.sql.Types.BIGINT);
680 preparedStatement.setDouble(5, attr.getValueDouble());
682 preparedStatement.setNull(5, java.sql.Types.DOUBLE);
685 connection.executeUpdate(preparedStatement);
687 }
catch (SQLException ex) {
688 throw new TskCoreException(String.format(
"Error updating attribute using query = '%s'", updateString), ex);
692 caseDb.releaseSingleUserCaseWriteLock();
706 CaseDbConnection connection =
null;
707 Statement statement =
null;
711 connection = caseDb.getConnection();
712 statement = connection.createStatement();
713 rs = connection.executeQuery(statement,
"SELECT attrs.id as id, attrs.obj_id AS obj_id, "
714 +
"attrs.attribute_type_id AS attribute_type_id, "
715 +
"attrs.value_type AS value_type, attrs.value_byte AS value_byte, "
716 +
"attrs.value_text AS value_text, attrs.value_int32 AS value_int32, "
717 +
"attrs.value_int64 AS value_int64, attrs.value_double AS value_double, "
718 +
"types.type_name AS type_name, types.display_name AS display_name "
719 +
"FROM tsk_file_attributes AS attrs "
720 +
" INNER JOIN blackboard_attribute_types AS types "
721 +
" ON attrs.attribute_type_id = types.attribute_type_id "
722 +
" WHERE attrs.obj_id = " + file.getId());
724 ArrayList<Attribute> attributes =
new ArrayList<Attribute>();
726 int attributeTypeId = rs.getInt(
"attribute_type_id");
727 String attributeTypeName = rs.getString(
"type_name");
729 if (this.typeIdToAttributeTypeMap.containsKey(attributeTypeId)) {
730 attributeType = this.typeIdToAttributeTypeMap.get(attributeTypeId);
732 attributeType =
new BlackboardAttribute.Type(attributeTypeId, attributeTypeName,
733 rs.getString(
"display_name"),
734 BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromType(rs.getInt(
"value_type")));
735 this.typeIdToAttributeTypeMap.put(attributeTypeId, attributeType);
736 this.typeNameToAttributeTypeMap.put(attributeTypeName, attributeType);
739 final Attribute attr =
new Attribute(
741 rs.getLong(
"obj_id"),
743 rs.getInt(
"value_int32"),
744 rs.getLong(
"value_int64"),
745 rs.getDouble(
"value_double"),
746 rs.getString(
"value_text"),
747 rs.getBytes(
"value_byte"), caseDb
749 attributes.add(attr);
752 }
catch (SQLException ex) {
753 throw new TskCoreException(
"Error getting attributes for file, file id = " + file.getId(), ex);
756 closeStatement(statement);
757 closeConnection(connection);
758 caseDb.releaseSingleUserCaseReadLock();
771 void initBlackboardArtifactTypes(CaseDbConnection connection)
throws SQLException {
772 caseDb.acquireSingleUserCaseWriteLock();
774 try (Statement getExistingStatement = connection.createStatement()) {
781 ResultSet resultSet = connection.executeQuery(getExistingStatement,
"SELECT artifact_type_id, type_name, display_name, category_type FROM blackboard_artifact_types");
782 while (resultSet.next()) {
783 BlackboardArtifact.Type type =
new BlackboardArtifact.Type(resultSet.getInt(
"artifact_type_id"),
784 resultSet.getString(
"type_name"), resultSet.getString(
"display_name"),
785 BlackboardArtifact.Category.fromID(resultSet.getInt(
"category_type")));
786 typeIdToArtifactTypeMap.put(type.getTypeID(), type);
787 typeNameToArtifactTypeMap.put(type.getTypeName(), type);
803 if (caseDb.getDatabaseType() == TskData.DbType.POSTGRESQL) {
804 insertSql =
"INSERT INTO blackboard_artifact_types (artifact_type_id, type_name, display_name, category_type) VALUES (?, ?, ?, ?) ON CONFLICT DO NOTHING";
806 insertSql =
"INSERT OR IGNORE INTO blackboard_artifact_types (artifact_type_id, type_name, display_name, category_type) VALUES (?, ?, ?, ?)";
809 for (BlackboardArtifact.ARTIFACT_TYPE type : BlackboardArtifact.ARTIFACT_TYPE.values()) {
810 if (typeIdToArtifactTypeMap.containsKey(type.getTypeID())) {
813 try (PreparedStatement insertArtType = connection.getPreparedStatement(insertSql, Statement.RETURN_GENERATED_KEYS)) {
814 insertArtType.setInt(1, type.getTypeID());
815 insertArtType.setString(2, type.getLabel());
816 insertArtType.setString(3, type.getDisplayName());
817 insertArtType.setInt(4, type.getCategory().getID());
818 insertArtType.executeUpdate();
820 typeIdToArtifactTypeMap.put(type.getTypeID(),
new BlackboardArtifact.Type(type));
821 typeNameToArtifactTypeMap.put(type.getLabel(),
new BlackboardArtifact.Type(type));
823 if (caseDb.getDatabaseType() == TskData.DbType.POSTGRESQL) {
824 int newPrimaryKeyIndex = Collections.max(Arrays.asList(BlackboardArtifact.ARTIFACT_TYPE.values())).getTypeID() + 1;
825 try (Statement updateSequenceStatement = connection.createStatement()) {
826 updateSequenceStatement.execute(
"ALTER SEQUENCE blackboard_artifact_types_artifact_type_id_seq RESTART WITH " + newPrimaryKeyIndex);
830 caseDb.releaseSingleUserCaseWriteLock();
843 void initBlackboardAttributeTypes(CaseDbConnection connection)
throws SQLException {
844 caseDb.acquireSingleUserCaseWriteLock();
845 try (Statement statement = connection.createStatement()) {
852 ResultSet resultSet = connection.executeQuery(statement,
"SELECT attribute_type_id, type_name, display_name, value_type FROM blackboard_attribute_types");
853 while (resultSet.next()) {
854 BlackboardAttribute.Type type =
new BlackboardAttribute.Type(resultSet.getInt(
"attribute_type_id"),
855 resultSet.getString(
"type_name"), resultSet.getString(
"display_name"),
856 BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromType(resultSet.getLong(
"value_type")));
857 typeIdToAttributeTypeMap.put(type.getTypeID(), type);
858 typeNameToAttributeTypeMap.put(type.getTypeName(), type);
872 for (BlackboardAttribute.ATTRIBUTE_TYPE type : BlackboardAttribute.ATTRIBUTE_TYPE.values()) {
873 if (typeIdToAttributeTypeMap.containsKey(type.getTypeID())) {
876 if (caseDb.getDatabaseType() == TskData.DbType.POSTGRESQL) {
877 statement.execute(
"INSERT INTO blackboard_attribute_types (attribute_type_id, type_name, display_name, value_type) VALUES (" + type.getTypeID() +
", '" + type.getLabel() +
"', '" + type.getDisplayName() +
"', '" + type.getValueType().getType() +
"') ON CONFLICT DO NOTHING");
879 statement.execute(
"INSERT OR IGNORE INTO blackboard_attribute_types (attribute_type_id, type_name, display_name, value_type) VALUES (" + type.getTypeID() +
", '" + type.getLabel() +
"', '" + type.getDisplayName() +
"', '" + type.getValueType().getType() +
"')");
881 typeIdToAttributeTypeMap.put(type.getTypeID(),
new BlackboardAttribute.Type(type));
882 typeNameToAttributeTypeMap.put(type.getLabel(),
new BlackboardAttribute.Type(type));
884 if (caseDb.getDatabaseType() == TskData.DbType.POSTGRESQL) {
885 int newPrimaryKeyIndex = Collections.max(Arrays.asList(BlackboardAttribute.ATTRIBUTE_TYPE.values())).getTypeID() + 1;
886 statement.execute(
"ALTER SEQUENCE blackboard_attribute_types_attribute_type_id_seq RESTART WITH " + newPrimaryKeyIndex);
889 caseDb.releaseSingleUserCaseWriteLock();
916 String conclusion, String configuration, String justification, Collection<BlackboardAttribute> attributesList)
920 throw new BlackboardException(String.format(
"Artifact type (name = %s) is not of Analysis Result category. ", artifactType.getTypeName()));
926 conclusion, configuration, justification, attributesList, transaction);
928 return analysisResult;
933 LOGGER.log(Level.SEVERE,
"Failed to rollback transaction after exception. "
934 +
"Error invoking newAnalysisResult with dataSourceObjId: "
935 + (dataSourceObjId ==
null ?
"<null>" : dataSourceObjId)
936 +
", sourceObjId: " + objId, ex2);
968 throw new BlackboardException(String.format(
"Artifact type (name = %s) is not of Analysis Result category. ", artifactType.getTypeName()));
973 AnalysisResult analysisResult = caseDb.
newAnalysisResult(artifactType, objId, dataSourceObjId, score, conclusion, configuration, justification, transaction.getConnection());
976 if (attributesList !=
null && !attributesList.isEmpty()) {
981 Score aggregateScore = caseDb.getScoringManager().updateAggregateScoreAfterAddition(objId, dataSourceObjId, analysisResult.
getScore(), transaction);
1015 if (transaction !=
null) {
1036 List<AnalysisResult> analysisResults =
getAnalysisResultsWhere(
" artifacts.artifact_obj_id = " + artifactObjId, transaction.getConnection());
1038 if (analysisResults.isEmpty()) {
1039 throw new TskCoreException(String.format(
"Analysis Result not found for artifact obj id %d", artifactObjId));
1061 CaseDbConnection connection = transaction.getConnection();
1064 String deleteSQL =
"DELETE FROM blackboard_artifacts WHERE artifact_obj_id = ?";
1066 PreparedStatement deleteStatement = connection.getPreparedStatement(deleteSQL, Statement.RETURN_GENERATED_KEYS);
1067 deleteStatement.clearParameters();
1068 deleteStatement.setLong(1, analysisResult.getId());
1070 deleteStatement.executeUpdate();
1073 transaction.registerDeletedAnalysisResult(analysisResult.getObjectID());
1075 return caseDb.
getScoringManager().updateAggregateScoreAfterDeletion(analysisResult.getObjectID(), analysisResult.getDataSourceObjectID(), transaction);
1077 }
catch (SQLException ex) {
1078 throw new TskCoreException(String.format(
"Error deleting analysis result with artifact obj id %d", analysisResult.getId()), ex);
1107 if (transaction !=
null) {
1131 List<AnalysisResult> analysisResults =
getAnalysisResultsWhere(
" artifacts.artifact_obj_id = " + artifactObjId, transaction.getConnection());
1133 if (analysisResults.isEmpty()) {
1134 throw new TskCoreException(String.format(
"Analysis Result not found for artifact obj id %d", artifactObjId));
1159 CaseDbConnection connection = transaction.getConnection();
1161 String query =
"UPDATE tsk_analysis_results SET ignore_score = CASE WHEN ? THEN 1 ELSE 0 END WHERE artifact_obj_id = ?";
1163 PreparedStatement ignoreScoreStatement = connection.getPreparedStatement(query, Statement.RETURN_GENERATED_KEYS);
1164 ignoreScoreStatement.clearParameters();
1165 ignoreScoreStatement.setBoolean(1, ignore);
1166 ignoreScoreStatement.setLong(2, analysisResult.getId());
1168 ignoreScoreStatement.executeUpdate();
1171 return caseDb.
getScoringManager().updateAggregateScoreAfterDeletion(analysisResult.getObjectID(), analysisResult.getDataSourceObjectID(), transaction);
1173 }
catch (SQLException ex) {
1174 throw new TskCoreException(String.format(
"Error ignoring score of analysis result with artifact obj id %d", analysisResult.getId()), ex);
1178 private final static String ANALYSIS_RESULT_QUERY_STRING_GENERIC =
"SELECT DISTINCT artifacts.artifact_id AS artifact_id, "
1179 +
" 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, "
1180 +
" types.type_name AS type_name, types.display_name AS display_name, types.category_type as category_type,"
1181 +
" artifacts.review_status_id AS review_status_id, "
1182 +
" results.conclusion AS conclusion, results.significance AS significance, results.priority AS priority, "
1183 +
" results.configuration AS configuration, results.justification AS justification, "
1184 +
" results.ignore_score AS ignore_score "
1185 +
" FROM blackboard_artifacts AS artifacts "
1186 +
" JOIN blackboard_artifact_types AS types "
1187 +
" ON artifacts.artifact_type_id = types.artifact_type_id"
1188 +
" LEFT JOIN tsk_analysis_results AS results "
1189 +
" ON artifacts.artifact_obj_id = results.artifact_obj_id ";
1191 private final static String ANALYSIS_RESULT_QUERY_STRING_WITH_ATTRIBUTES
1192 = ANALYSIS_RESULT_QUERY_STRING_GENERIC
1193 +
" JOIN blackboard_attributes AS attributes "
1194 +
" ON artifacts.artifact_id = attributes.artifact_id "
1195 +
" WHERE types.category_type = " + BlackboardArtifact.Category.ANALYSIS_RESULT.getID();
1197 private final static String ANALYSIS_RESULT_QUERY_STRING_WHERE
1198 = ANALYSIS_RESULT_QUERY_STRING_GENERIC
1199 +
" WHERE artifacts.review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID()
1200 +
" AND types.category_type = " + BlackboardArtifact.Category.ANALYSIS_RESULT.getID();
1228 return getAnalysisResultsWhere(
" artifacts.artifact_type_id = " + artifactTypeId +
" AND artifacts.data_source_obj_id = " + dataSourceObjId);
1245 caseDb.acquireSingleUserCaseReadLock();
1246 try (CaseDbConnection connection = caseDb.getConnection()) {
1247 String whereClause =
" artifacts.data_source_obj_id = " + dataSourceObjId;
1248 if (artifactTypeID !=
null) {
1249 whereClause +=
" AND artifacts.artifact_type_id = " + artifactTypeID;
1253 caseDb.releaseSingleUserCaseReadLock();
1281 List<DataArtifact> getDataArtifactsBySource(
long sourceObjId)
throws TskCoreException {
1283 try (CaseDbConnection connection = caseDb.getConnection()) {
1330 String queryString =
"SELECT COUNT(*) AS count "
1331 +
" FROM blackboard_artifacts AS arts "
1332 +
" JOIN blackboard_artifact_types AS types "
1333 +
" ON arts.artifact_type_id = types.artifact_type_id"
1334 +
" WHERE types.category_type = " + category.getID()
1335 +
" AND arts.obj_id = " + sourceObjId;
1339 Statement statement = connection.createStatement();
1340 ResultSet resultSet = connection.executeQuery(statement, queryString);) {
1341 if (resultSet.next()) {
1342 return resultSet.getLong(
"count") > 0;
1345 }
catch (SQLException ex) {
1346 throw new TskCoreException(
"Error getting artifact types is use for data source." + ex.getMessage(), ex);
1364 List<AnalysisResult>
getAnalysisResults(
long sourceObjId, CaseDbConnection connection)
throws TskCoreException {
1383 throw new TskCoreException(String.format(
"Artifact type id %d is not in analysis result catgeory.", artifactTypeId));
1386 String whereClause =
" types.artifact_type_id = " + artifactTypeId
1387 +
" AND artifacts.obj_id = " + sourceObjId;
1403 caseDb.acquireSingleUserCaseReadLock();
1404 try (CaseDbConnection connection = caseDb.getConnection()) {
1407 caseDb.releaseSingleUserCaseReadLock();
1425 final String queryString = ANALYSIS_RESULT_QUERY_STRING_WHERE
1426 +
" AND " + whereClause;
1428 try (Statement statement = connection.createStatement();
1429 ResultSet resultSet = connection.executeQuery(statement, queryString);) {
1431 List<AnalysisResult> analysisResults = resultSetToAnalysisResults(resultSet);
1432 return analysisResults;
1433 }
catch (SQLException ex) {
1434 throw new TskCoreException(String.format(
"Error getting analysis results for WHERE clause = '%s'", whereClause), ex);
1449 String whereClause =
" artifacts.artifact_obj_id = " + artifactObjId;
1452 if (results.isEmpty()) {
1453 throw new TskCoreException(String.format(
"Error getting analysis result with id = '%d'", artifactObjId));
1455 if (results.size() > 1) {
1456 throw new TskCoreException(String.format(
"Multiple analysis results found with id = '%d'", artifactObjId));
1459 return results.get(0);
1477 private List<AnalysisResult> resultSetToAnalysisResults(ResultSet resultSet)
throws SQLException,
TskCoreException {
1478 ArrayList<AnalysisResult> analysisResults =
new ArrayList<>();
1480 while (resultSet.next()) {
1481 analysisResults.add(
new AnalysisResult(caseDb, resultSet.getLong(
"artifact_id"), resultSet.getLong(
"obj_id"),
1482 resultSet.getLong(
"artifact_obj_id"),
1483 resultSet.getObject(
"data_source_obj_id") !=
null ? resultSet.getLong(
"data_source_obj_id") :
null,
1484 resultSet.getInt(
"artifact_type_id"), resultSet.getString(
"type_name"), resultSet.getString(
"display_name"),
1487 resultSet.getString(
"conclusion"), resultSet.getString(
"configuration"), resultSet.getString(
"justification"),
1488 resultSet.getBoolean(
"ignore_score")));
1491 return analysisResults;
1494 private final static String DATA_ARTIFACT_QUERY_STRING_GENERIC =
"SELECT DISTINCT artifacts.artifact_id AS artifact_id, "
1495 +
"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, "
1496 +
" types.type_name AS type_name, types.display_name AS display_name, types.category_type as category_type,"
1497 +
" artifacts.review_status_id AS review_status_id, "
1498 +
" data_artifacts.os_account_obj_id as os_account_obj_id "
1499 +
" FROM blackboard_artifacts AS artifacts "
1500 +
" JOIN blackboard_artifact_types AS types "
1501 +
" ON artifacts.artifact_type_id = types.artifact_type_id"
1502 +
" LEFT JOIN tsk_data_artifacts AS data_artifacts "
1503 +
" ON artifacts.artifact_obj_id = data_artifacts.artifact_obj_id ";
1505 private final static String DATA_ARTIFACT_QUERY_STRING_WITH_ATTRIBUTES
1506 = DATA_ARTIFACT_QUERY_STRING_GENERIC
1507 +
" JOIN blackboard_attributes AS attributes "
1508 +
" ON artifacts.artifact_id = attributes.artifact_id "
1509 +
" WHERE types.category_type = " + BlackboardArtifact.Category.DATA_ARTIFACT.getID();
1511 private final static String DATA_ARTIFACT_QUERY_STRING_WHERE
1512 = DATA_ARTIFACT_QUERY_STRING_GENERIC
1513 +
" WHERE artifacts.review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID()
1514 +
" AND types.category_type = " + BlackboardArtifact.Category.DATA_ARTIFACT.getID();
1529 caseDb.acquireSingleUserCaseReadLock();
1530 try (CaseDbConnection connection = caseDb.getConnection()) {
1531 String whereClause =
" artifacts.data_source_obj_id = " + dataSourceObjId;
1532 if (artifactTypeID !=
null) {
1533 whereClause +=
" AND artifacts.artifact_type_id = " + artifactTypeID;
1537 caseDb.releaseSingleUserCaseReadLock();
1557 throw new TskCoreException(String.format(
"Artifact type id %d is not in data artifact catgeory.", artifactTypeID));
1560 caseDb.acquireSingleUserCaseReadLock();
1561 try (CaseDbConnection connection = caseDb.getConnection()) {
1562 String whereClause =
"artifacts.data_source_obj_id = " + dataSourceObjId
1563 +
" AND artifacts.artifact_type_id = " + artifactTypeID;
1567 caseDb.releaseSingleUserCaseReadLock();
1585 throw new TskCoreException(String.format(
"Artifact type id %d is not in data artifact catgeory.", artifactTypeID));
1588 caseDb.acquireSingleUserCaseReadLock();
1589 try (CaseDbConnection connection = caseDb.getConnection()) {
1590 String whereClause =
" artifacts.artifact_type_id = " + artifactTypeID;
1594 caseDb.releaseSingleUserCaseReadLock();
1609 caseDb.acquireSingleUserCaseReadLock();
1610 try (CaseDbConnection connection = caseDb.getConnection()) {
1611 String whereClause =
" artifacts.artifact_obj_id = " + artifactObjId;
1614 if (artifacts.isEmpty()) {
1615 throw new TskCoreException(String.format(
"Error getting data artifact with id = '%d'", artifactObjId));
1617 if (artifacts.size() > 1) {
1618 throw new TskCoreException(String.format(
"Multiple data artifacts found with id = '%d'", artifactObjId));
1621 return artifacts.get(0);
1623 caseDb.releaseSingleUserCaseReadLock();
1638 caseDb.acquireSingleUserCaseReadLock();
1639 try (CaseDbConnection connection = caseDb.getConnection()) {
1642 caseDb.releaseSingleUserCaseReadLock();
1660 final String queryString = DATA_ARTIFACT_QUERY_STRING_WHERE
1661 +
" AND " + whereClause +
" ";
1663 try (Statement statement = connection.createStatement();
1664 ResultSet resultSet = connection.executeQuery(statement, queryString);) {
1666 List<DataArtifact> dataArtifacts = resultSetToDataArtifacts(resultSet);
1667 return dataArtifacts;
1668 }
catch (SQLException ex) {
1669 throw new TskCoreException(String.format(
"Error getting data artifacts with queryString = %s", queryString), ex);
1688 private List<DataArtifact> resultSetToDataArtifacts(ResultSet resultSet)
throws SQLException, TskCoreException {
1689 ArrayList<DataArtifact> dataArtifacts =
new ArrayList<>();
1691 while (resultSet.next()) {
1693 Long osAccountObjId = resultSet.getLong(
"os_account_obj_id");
1694 if (resultSet.wasNull()) {
1695 osAccountObjId =
null;
1698 dataArtifacts.add(
new DataArtifact(caseDb, resultSet.getLong(
"artifact_id"), resultSet.getLong(
"obj_id"),
1699 resultSet.getLong(
"artifact_obj_id"),
1700 resultSet.getObject(
"data_source_obj_id") !=
null ? resultSet.getLong(
"data_source_obj_id") :
null,
1701 resultSet.getInt(
"artifact_type_id"), resultSet.getString(
"type_name"), resultSet.getString(
"display_name"),
1702 BlackboardArtifact.ReviewStatus.withID(resultSet.getInt(
"review_status_id")), osAccountObjId,
false));
1705 return dataArtifacts;
1727 if (typeNameToAttributeTypeMap.containsKey(typeName)) {
1728 return typeNameToAttributeTypeMap.get(typeName);
1734 String matchingAttrQuery =
"SELECT attribute_type_id, type_name, display_name, value_type "
1735 +
"FROM blackboard_attribute_types WHERE type_name = ?";
1737 PreparedStatement query = trans.getConnection().getPreparedStatement(matchingAttrQuery, Statement.RETURN_GENERATED_KEYS);
1738 query.clearParameters();
1739 query.setString(1, typeName);
1740 try (ResultSet rs = query.executeQuery()) {
1746 rs.getInt(
"attribute_type_id"),
1747 rs.getString(
"type_name"),
1748 rs.getString(
"display_name"),
1752 this.typeIdToAttributeTypeMap.put(foundType.getTypeID(), foundType);
1753 this.typeNameToAttributeTypeMap.put(foundType.getTypeName(), foundType);
1760 String insertStatement =
"INSERT INTO blackboard_attribute_types (attribute_type_id, type_name, display_name, value_type) VALUES (\n"
1762 +
"(SELECT MAX(q.attribute_type_id) FROM (SELECT attribute_type_id FROM blackboard_attribute_types UNION SELECT " + (MIN_USER_DEFINED_TYPE_ID - 1) +
") q) + 1,\n"
1766 PreparedStatement insertPreparedStatement = trans.getConnection().getPreparedStatement(insertStatement, Statement.RETURN_GENERATED_KEYS);
1767 insertPreparedStatement.clearParameters();
1768 insertPreparedStatement.setString(1, typeName);
1769 insertPreparedStatement.setString(2, displayName);
1770 insertPreparedStatement.setLong(3, valueType.getType());
1772 int numUpdated = insertPreparedStatement.executeUpdate();
1775 Integer attrId =
null;
1777 if (numUpdated > 0) {
1778 try (ResultSet insertResult = insertPreparedStatement.getGeneratedKeys()) {
1779 if (insertResult.next()) {
1780 attrId = insertResult.getInt(1);
1785 if (attrId ==
null) {
1787 "Error adding attribute type. Item with name {0} was not inserted successfully into the database.", typeName));
1794 this.typeIdToAttributeTypeMap.put(type.getTypeID(), type);
1795 this.typeNameToAttributeTypeMap.put(type.getTypeName(), type);
1801 if (trans !=
null) {
1806 LOGGER.log(Level.SEVERE,
"Error rolling back transaction", ex2);
1824 final String queryString =
"SELECT DISTINCT arts.artifact_type_id AS artifact_type_id, "
1825 +
"types.type_name AS type_name, "
1826 +
"types.display_name AS display_name, "
1827 +
"types.category_type AS category_type "
1828 +
"FROM blackboard_artifact_types AS types "
1829 +
"INNER JOIN blackboard_artifacts AS arts "
1830 +
"ON arts.artifact_type_id = types.artifact_type_id "
1831 +
"WHERE arts.data_source_obj_id = " + dataSourceObjId;
1833 caseDb.acquireSingleUserCaseReadLock();
1835 Statement statement = connection.createStatement();
1836 ResultSet resultSet = connection.executeQuery(statement, queryString);) {
1839 while (resultSet.next()) {
1841 resultSet.getString(
"type_name"), resultSet.getString(
"display_name"),
1844 return uniqueArtifactTypes;
1845 }
catch (SQLException ex) {
1846 throw new TskCoreException(
"Error getting artifact types is use for data source." + ex.getMessage(), ex);
1848 caseDb.releaseSingleUserCaseReadLock();
1865 return getArtifactsCountHelper(artifactTypeID,
1866 "blackboard_artifacts.data_source_obj_id = '" + dataSourceObjId +
"';");
1881 return getArtifactsCountHelper(artifactTypeID,
null);
1897 String whereClause = String.format(
"artifacts.data_source_obj_id = %d", dataSourceObjId);
1898 return getArtifactsWhere(
getArtifactType(artifactTypeID), whereClause);
1913 public List<BlackboardArtifact>
getArtifacts(Collection<BlackboardArtifact.Type> artifactTypes,
1916 if (artifactTypes.isEmpty() || dataSourceObjIds.isEmpty()) {
1917 return new ArrayList<>();
1920 String analysisResultQuery =
"";
1921 String dataArtifactQuery =
"";
1925 if (!analysisResultQuery.isEmpty()) {
1926 analysisResultQuery +=
" OR ";
1928 analysisResultQuery +=
"types.artifact_type_id = " + type.getTypeID();
1930 if (!dataArtifactQuery.isEmpty()) {
1931 dataArtifactQuery +=
" OR ";
1933 dataArtifactQuery +=
"types.artifact_type_id = " + type.getTypeID();
1937 String dsQuery =
"";
1938 for (
long dsId : dataSourceObjIds) {
1939 if (!dsQuery.isEmpty()) {
1942 dsQuery +=
"artifacts.data_source_obj_id = " + dsId;
1945 List<BlackboardArtifact> artifacts =
new ArrayList<>();
1947 if (!analysisResultQuery.isEmpty()) {
1948 String fullQuery =
"( " + analysisResultQuery +
" ) AND (" + dsQuery +
") ";
1952 if (!dataArtifactQuery.isEmpty()) {
1953 String fullQuery =
"( " + dataArtifactQuery +
" ) AND (" + dsQuery +
") ";
1980 String query =
" AND artifacts.artifact_type_id = " + artifactType.getTypeID()
1981 +
" AND attributes.attribute_type_id = " + attributeType.getTypeID()
1982 + ((value ==
null || value.isEmpty()) ?
"" :
" AND attributes.value_text = '" + value +
"'")
1984 + (dataSourceObjId !=
null ?
" AND artifacts.data_source_obj_id = " + dataSourceObjId :
"");
1986 List<BlackboardArtifact> artifacts =
new ArrayList<>();
1987 caseDb.acquireSingleUserCaseReadLock();
1990 ? ANALYSIS_RESULT_QUERY_STRING_WITH_ATTRIBUTES + query
1991 : DATA_ARTIFACT_QUERY_STRING_WITH_ATTRIBUTES + query);
1993 try (CaseDbConnection connection = caseDb.getConnection()) {
1994 try (Statement statement = connection.createStatement();
1995 ResultSet resultSet = connection.executeQuery(statement, finalQuery);) {
1998 artifacts.addAll(resultSetToAnalysisResults(resultSet));
2000 artifacts.addAll(resultSetToDataArtifacts(resultSet));
2002 }
catch (SQLException ex) {
2003 throw new TskCoreException(String.format(
"Error getting results with queryString = '%s'", finalQuery), ex);
2006 caseDb.releaseSingleUserCaseReadLock();
2063 String dataSourceClause = dataSourceId ==
null
2065 :
" AND artifacts.data_source_obj_id = ? ";
2067 String kwsListClause = (kwsListName ==
null || kwsListName.isEmpty()
2068 ?
" WHERE r.set_name IS NULL "
2069 :
" WHERE r.set_name = ? ");
2071 String keywordClause = (keyword ==
null || keyword.isEmpty()
2073 :
" AND r.keyword = ? ");
2075 String searchTypeClause = (searchType ==
null
2077 :
" AND r.search_type = ? ");
2079 String regexClause = (regex ==
null || regex.isEmpty()
2081 :
" AND r.regexp_str = ? ");
2083 String query =
"SELECT r.* FROM ( "
2084 +
" SELECT DISTINCT artifacts.artifact_id AS artifact_id, "
2085 +
" artifacts.obj_id AS obj_id, "
2086 +
" artifacts.artifact_obj_id AS artifact_obj_id, "
2087 +
" artifacts.data_source_obj_id AS data_source_obj_id, "
2088 +
" artifacts.artifact_type_id AS artifact_type_id, "
2089 +
" types.type_name AS type_name, "
2090 +
" types.display_name AS display_name, "
2091 +
" types.category_type as category_type,"
2092 +
" artifacts.review_status_id AS review_status_id, "
2093 +
" results.conclusion AS conclusion, "
2094 +
" results.significance AS significance, "
2095 +
" results.priority AS priority, "
2096 +
" results.configuration AS configuration, "
2097 +
" results.justification AS justification, "
2098 +
" (SELECT value_text FROM blackboard_attributes attr WHERE attr.artifact_id = artifacts.artifact_id AND attr.attribute_type_id = "
2100 +
" (SELECT value_int32 FROM blackboard_attributes attr WHERE attr.artifact_id = artifacts.artifact_id AND attr.attribute_type_id = "
2102 +
" (SELECT value_text FROM blackboard_attributes attr WHERE attr.artifact_id = artifacts.artifact_id AND attr.attribute_type_id = "
2104 +
" (SELECT value_text FROM blackboard_attributes attr WHERE attr.artifact_id = artifacts.artifact_id AND attr.attribute_type_id = "
2106 +
" FROM blackboard_artifacts artifacts "
2107 +
" JOIN blackboard_artifact_types AS types "
2108 +
" ON artifacts.artifact_type_id = types.artifact_type_id "
2109 +
" LEFT JOIN tsk_analysis_results AS results "
2110 +
" ON artifacts.artifact_obj_id = results.artifact_obj_id "
2113 + dataSourceClause +
" ) r "
2119 List<BlackboardArtifact> artifacts =
new ArrayList<>();
2120 caseDb.acquireSingleUserCaseReadLock();
2121 try (CaseDbConnection connection = caseDb.getConnection()) {
2124 PreparedStatement preparedStatement = connection.getPreparedStatement(query, Statement.RETURN_GENERATED_KEYS);
2125 preparedStatement.clearParameters();
2127 if (dataSourceId !=
null) {
2128 preparedStatement.setLong(++paramIdx, dataSourceId);
2131 if (!(kwsListName ==
null || kwsListName.isEmpty())) {
2132 preparedStatement.setString(++paramIdx, kwsListName);
2135 if (!(keyword ==
null || keyword.isEmpty())) {
2136 preparedStatement.setString(++paramIdx, keyword);
2139 if (searchType !=
null) {
2140 preparedStatement.setInt(++paramIdx, searchType.getType());
2143 if (!(regex ==
null || regex.isEmpty())) {
2144 preparedStatement.setString(++paramIdx, regex);
2147 try (ResultSet resultSet = connection.executeQuery(preparedStatement)) {
2148 artifacts.addAll(resultSetToAnalysisResults(resultSet));
2151 }
catch (SQLException ex) {
2152 throw new TskCoreException(String.format(
"Error getting keyword search results with queryString = '%s'", query), ex);
2155 caseDb.releaseSingleUserCaseReadLock();
2173 private long getArtifactsCountHelper(
int artifactTypeID, String whereClause)
throws TskCoreException {
2174 String queryString =
"SELECT COUNT(*) AS count FROM blackboard_artifacts "
2175 +
"WHERE blackboard_artifacts.artifact_type_id = " + artifactTypeID
2178 if (whereClause !=
null) {
2179 queryString +=
" AND " + whereClause;
2183 try (SleuthkitCase.CaseDbConnection connection = caseDb.getConnection();
2184 Statement statement = connection.createStatement();
2185 ResultSet resultSet = connection.executeQuery(statement, queryString);) {
2187 if (resultSet.next()) {
2188 count = resultSet.getLong(
"count");
2191 }
catch (SQLException ex) {
2192 throw new TskCoreException(
"Error getting artifact types is use for data source." + ex.getMessage(), ex);
2194 caseDb.releaseSingleUserCaseReadLock();
2212 List<BlackboardArtifact> existingArtifacts = content.getArtifacts(artifactType.getTypeID());
2214 if (attributesMatch(artifact.getAttributes(), attributes)) {
2250 private boolean attributesMatch(Collection<BlackboardAttribute> fileAttributesList, Collection<BlackboardAttribute> expectedAttributesList) {
2252 boolean match =
false;
2255 if (attributeType.getTypeID() != expectedAttribute.getAttributeType().getTypeID()) {
2259 Object fileAttributeValue;
2260 Object expectedAttributeValue;
2261 switch (attributeType.getValueType()) {
2263 fileAttributeValue = fileAttribute.getValueBytes();
2264 expectedAttributeValue = expectedAttribute.getValueBytes();
2267 fileAttributeValue = fileAttribute.getValueDouble();
2268 expectedAttributeValue = expectedAttribute.getValueDouble();
2271 fileAttributeValue = fileAttribute.getValueInt();
2272 expectedAttributeValue = expectedAttribute.getValueInt();
2276 fileAttributeValue = fileAttribute.getValueLong();
2277 expectedAttributeValue = expectedAttribute.getValueLong();
2281 fileAttributeValue = fileAttribute.getValueString();
2282 expectedAttributeValue = expectedAttribute.getValueString();
2285 fileAttributeValue = fileAttribute.getDisplayString();
2286 expectedAttributeValue = expectedAttribute.getDisplayString();
2294 if (fileAttributeValue instanceof
byte[]) {
2295 if (Arrays.equals((
byte[]) fileAttributeValue, (
byte[]) expectedAttributeValue)) {
2299 }
else if (fileAttributeValue.equals(expectedAttributeValue)) {
2323 public static final class BlackboardException
extends Exception {
2325 private static final long serialVersionUID = 1L;
2332 BlackboardException(String message) {
2343 BlackboardException(String message, Throwable cause) {
2344 super(message, cause);
2365 Collection<BlackboardAttribute> attributes, Long osAccountId)
throws TskCoreException {
2368 throw new TskCoreException(String.format(
"Artifact type (name = %s) is not of Data Artifact category. ", artifactType.getTypeName()));
2374 attributes, osAccountId, transaction);
2376 return dataArtifact;
2381 LOGGER.log(Level.SEVERE,
"Failed to rollback transaction after exception. "
2382 +
"Error invoking newDataArtifact with dataSourceObjId: " + dataSourceObjId +
", sourceObjId: " + sourceObjId, ex2);
2439 Collection<BlackboardAttribute> attributes,
2444 throw new TskCoreException(String.format(
"Artifact type (name = %s) is not of Data Artifact category. ", artifactType.getTypeName()));
2448 CaseDbConnection connection = transaction.getConnection();
2450 PreparedStatement statement = caseDb.createInsertArtifactStatement(artifactType.getTypeID(), sourceObjId, artifact_obj_id, dataSourceObjId, connection);
2452 connection.executeUpdate(statement);
2453 try (ResultSet resultSet = statement.getGeneratedKeys()) {
2456 sourceObjId, artifact_obj_id, dataSourceObjId, artifactType.getTypeID(),
2458 osAccountObjId,
true);
2461 if (osAccountObjId !=
null) {
2462 String insertDataArtifactSQL =
"INSERT INTO tsk_data_artifacts (artifact_obj_id, os_account_obj_id) VALUES (?, ?)";
2464 statement = connection.getPreparedStatement(insertDataArtifactSQL, Statement.NO_GENERATED_KEYS);
2465 statement.clearParameters();
2467 statement.setLong(1, artifact_obj_id);
2468 statement.setLong(2, osAccountObjId);
2469 connection.executeUpdate(statement);
2472 if (Objects.nonNull(osAccountInstanceType)) {
2473 caseDb.getOsAccountManager().newOsAccountInstance(osAccountObjId, dataSourceObjId, osAccountInstanceType, connection);
2478 if (Objects.nonNull(attributes) && !attributes.isEmpty()) {
2482 return dataArtifact;
2484 }
catch (SQLException ex) {
2485 throw new TskCoreException(String.format(
"Error creating a data artifact with type id = %d, objId = %d, and data source oj id = %d ", artifactType.getTypeID(), sourceObjId, dataSourceObjId), ex);
2501 String whereClause = String.format(
"artifacts.obj_id = %d", sourceObjId);
2502 return getArtifactsWhere(artifactType, whereClause);
2514 List<BlackboardArtifact> getArtifactsByType(BlackboardArtifact.Type artifactType)
throws TskCoreException {
2515 List<BlackboardArtifact> artifacts =
new ArrayList<>();
2516 if (artifactType.getCategory() == BlackboardArtifact.Category.ANALYSIS_RESULT) {
2541 private List<BlackboardArtifact> getArtifactsWhere(BlackboardArtifact.Type artifactType, String whereClause)
throws TskCoreException {
2542 List<BlackboardArtifact> artifacts =
new ArrayList<>();
2543 String whereWithType = whereClause +
" AND artifacts.artifact_type_id = " + artifactType.getTypeID();
2545 if (artifactType.getCategory() == BlackboardArtifact.Category.ANALYSIS_RESULT) {
2559 final public class ArtifactsPostedEvent {
2561 private final String moduleName;
2563 private final ImmutableSet<BlackboardArtifact> artifacts;
2564 private final Long ingestJobId;
2577 private ArtifactsPostedEvent(Collection<BlackboardArtifact> artifacts, String moduleName, Long ingestJobId)
throws BlackboardException {
2578 Set<Integer> typeIDS = artifacts.stream()
2580 .collect(Collectors.toSet());
2582 for (Integer typeID : typeIDS) {
2589 artifactTypes = ImmutableSet.copyOf(types);
2590 this.artifacts = ImmutableSet.copyOf(artifacts);
2591 this.moduleName = moduleName;
2592 this.ingestJobId = ingestJobId;
2601 return ImmutableSet.copyOf(artifacts);
2612 Set<BlackboardArtifact> tempSet = artifacts.stream()
2613 .filter(artifact -> artifact.getArtifactTypeID() == artifactType.getTypeID())
2614 .collect(Collectors.toSet());
2615 return ImmutableSet.copyOf(tempSet);
2633 return ImmutableSet.copyOf(artifactTypes);
2643 return Optional.ofNullable(ingestJobId);