19 package org.sleuthkit.datamodel;
 
   21 import com.google.common.annotations.Beta;
 
   22 import com.google.common.collect.ImmutableSet;
 
   23 import java.sql.PreparedStatement;
 
   24 import java.sql.ResultSet;
 
   25 import java.sql.SQLException;
 
   26 import java.sql.Statement;
 
   27 import java.text.MessageFormat;
 
   28 import java.util.ArrayList;
 
   29 import java.util.Arrays;
 
   30 import java.util.Collection;
 
   31 import java.util.Collections;
 
   32 import java.util.HashMap;
 
   33 import java.util.HashSet;
 
   34 import java.util.List;
 
   36 import java.util.Objects;
 
   37 import java.util.Optional;
 
   39 import java.util.concurrent.ConcurrentHashMap;
 
   40 import java.util.logging.Level;
 
   41 import java.util.logging.Logger;
 
   42 import java.util.stream.Collectors;
 
   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);
 
  162                                 throw new BlackboardException(String.format(
"Failed to add events to timeline for artifact '%s'", artifact), ex);
 
  200                 if (category == null) {
 
  201                         throw new BlackboardException(
"Category provided must be non-null");
 
  204                 if (typeNameToArtifactTypeMap.containsKey(typeName)) {
 
  205                         return typeNameToArtifactTypeMap.get(typeName);
 
  214                         CaseDbConnection connection = trans.getConnection();
 
  215                         s = connection.createStatement();
 
  216                         rs = connection.executeQuery(s, 
"SELECT artifact_type_id FROM blackboard_artifact_types WHERE type_name = '" + typeName + 
"'"); 
 
  219                                 rs = connection.executeQuery(s, 
"SELECT MAX(artifact_type_id) AS highest_id FROM blackboard_artifact_types");
 
  222                                         maxID = rs.getInt(
"highest_id");
 
  223                                         if (maxID < MIN_USER_DEFINED_TYPE_ID) {
 
  224                                                 maxID = MIN_USER_DEFINED_TYPE_ID;
 
  229                                 connection.executeUpdate(s, 
"INSERT INTO blackboard_artifact_types (artifact_type_id, type_name, display_name, category_type) VALUES ('" + maxID + 
"', '" + typeName + 
"', '" + displayName + 
"', " + category.getID() + 
" )"); 
 
  231                                 this.typeIdToArtifactTypeMap.put(type.getTypeID(), type);
 
  232                                 this.typeNameToArtifactTypeMap.put(type.getTypeName(), type);
 
  242                                         throw new BlackboardException(
"Failed to get or add artifact type: " + typeName, ex);
 
  252                                 LOGGER.log(Level.SEVERE, 
"Error rolling back transaction", ex2);
 
  254                         throw new BlackboardException(
"Error adding artifact type: " + typeName, ex);
 
  262                                         throw new BlackboardException(
"Error rolling back transaction", ex);
 
  279                 if (this.typeNameToAttributeTypeMap.containsKey(attrTypeName)) {
 
  280                         return this.typeNameToAttributeTypeMap.get(attrTypeName);
 
  282                 CaseDbConnection connection = null;
 
  287                         connection = caseDb.getConnection();
 
  288                         s = connection.createStatement();
 
  289                         rs = connection.executeQuery(s, 
"SELECT attribute_type_id, type_name, display_name, value_type FROM blackboard_attribute_types WHERE type_name = '" + attrTypeName + 
"'"); 
 
  294                                 this.typeIdToAttributeTypeMap.put(type.getTypeID(), type);
 
  295                                 this.typeNameToAttributeTypeMap.put(attrTypeName, type);
 
  298                 } 
catch (SQLException ex) {
 
  303                         closeConnection(connection);
 
  319                 if (this.typeIdToAttributeTypeMap.containsKey(typeID)) {
 
  320                         return this.typeIdToAttributeTypeMap.get(typeID);
 
  322                 CaseDbConnection connection = null;
 
  327                         connection = caseDb.getConnection();
 
  328                         s = connection.createStatement();
 
  329                         rs = connection.executeQuery(s, 
"SELECT attribute_type_id, type_name, display_name, value_type FROM blackboard_attribute_types WHERE attribute_type_id = " + typeID + 
""); 
 
  330                         BlackboardAttribute.Type type = null;
 
  332                                 type = 
new BlackboardAttribute.Type(rs.getInt(
"attribute_type_id"), rs.getString(
"type_name"),
 
  333                                                 rs.getString(
"display_name"), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromType(rs.getLong(
"value_type")));
 
  334                                 this.typeIdToAttributeTypeMap.put(typeID, type);
 
  335                                 this.typeNameToAttributeTypeMap.put(type.getTypeName(), type);
 
  338                 } 
catch (SQLException ex) {
 
  339                         throw new TskCoreException(
"Error getting attribute type id", ex);
 
  343                         closeConnection(connection);
 
  359                 if (this.typeNameToArtifactTypeMap.containsKey(artTypeName)) {
 
  360                         return this.typeNameToArtifactTypeMap.get(artTypeName);
 
  362                 CaseDbConnection connection = null;
 
  367                         connection = caseDb.getConnection();
 
  368                         s = connection.createStatement();
 
  369                         rs = connection.executeQuery(s, 
"SELECT artifact_type_id, type_name, display_name, category_type FROM blackboard_artifact_types WHERE type_name = '" + artTypeName + 
"'"); 
 
  373                                                 rs.getString(
"type_name"), rs.getString(
"display_name"),
 
  375                                 this.typeIdToArtifactTypeMap.put(type.getTypeID(), type);
 
  376                                 this.typeNameToArtifactTypeMap.put(artTypeName, type);
 
  379                 } 
catch (SQLException ex) {
 
  380                         throw new TskCoreException(
"Error getting artifact type from the database", ex);
 
  384                         closeConnection(connection);
 
  401                 if (this.typeIdToArtifactTypeMap.containsKey(artTypeId)) {
 
  402                         return typeIdToArtifactTypeMap.get(artTypeId);
 
  404                 CaseDbConnection connection = null;
 
  409                         connection = caseDb.getConnection();
 
  410                         s = connection.createStatement();
 
  411                         rs = connection.executeQuery(s, 
"SELECT artifact_type_id, type_name, display_name, category_type FROM blackboard_artifact_types WHERE artifact_type_id = " + artTypeId + 
""); 
 
  415                                                 rs.getString(
"type_name"), rs.getString(
"display_name"),
 
  417                                 this.typeIdToArtifactTypeMap.put(artTypeId, type);
 
  418                                 this.typeNameToArtifactTypeMap.put(type.getTypeName(), type);
 
  421                                 throw new TskCoreException(
"No artifact type found matching id: " + artTypeId);
 
  423                 } 
catch (SQLException ex) {
 
  424                         throw new TskCoreException(
"Error getting artifact type from the database", ex);
 
  428                         closeConnection(connection);
 
  443                 CaseDbConnection connection = null;
 
  444                 Statement statement = null;
 
  450                                 rowId = 
"attrs.CTID";
 
  453                                 rowId = 
"attrs.ROWID";
 
  461                         connection = caseDb.getConnection();
 
  462                         statement = connection.createStatement();
 
  463                         rs = connection.executeQuery(statement, 
"SELECT attrs.artifact_id AS artifact_id, " 
  464                                         + 
"attrs.source AS source, attrs.context AS context, attrs.attribute_type_id AS attribute_type_id, " 
  465                                         + 
"attrs.value_type AS value_type, attrs.value_byte AS value_byte, " 
  466                                         + 
"attrs.value_text AS value_text, attrs.value_int32 AS value_int32, " 
  467                                         + 
"attrs.value_int64 AS value_int64, attrs.value_double AS value_double, " 
  468                                         + 
"types.type_name AS type_name, types.display_name AS display_name " 
  469                                         + 
"FROM blackboard_attributes AS attrs, blackboard_attribute_types AS types WHERE attrs.artifact_id = " + artifact.getArtifactID()
 
  470                                         + 
" AND attrs.attribute_type_id = types.attribute_type_id "  
  471                                         + 
" ORDER BY " + rowId);
 
  472                         ArrayList<BlackboardAttribute> attributes = 
new ArrayList<>();
 
  475                                 attr.setParentDataSourceID(artifact.getDataSourceObjectID());
 
  476                                 attributes.add(attr);
 
  479                 } 
catch (SQLException ex) {
 
  480                         throw new TskCoreException(
"Error getting attributes for artifact, artifact id = " + artifact.getArtifactID(), ex);
 
  483                         closeStatement(statement);
 
  484                         closeConnection(connection);
 
  500         public <T extends BlackboardArtifact> 
void loadBlackboardAttributes(List<T> arts) 
throws TskCoreException {
 
  502                 if (arts.isEmpty()) {
 
  507                 Map<Long, BlackboardArtifact> artifactMap = 
new HashMap<>();
 
  508                 for (BlackboardArtifact art : arts) {
 
  509                         artifactMap.put(art.getArtifactID(), art);
 
  513                 Map<Long, List<BlackboardAttribute>> attributeMap = 
new HashMap<>();
 
  516                 String idString = arts.stream().map(p -> Long.toString(p.getArtifactID())).collect(Collectors.joining(
", "));
 
  521                                 rowId = 
"attrs.CTID";
 
  524                                 rowId = 
"attrs.ROWID";
 
  527                                 throw new TskCoreException(
"Unknown database type: " + caseDb.
getDatabaseType());
 
  531                 CaseDbConnection connection = null;
 
  532                 Statement statement = null;
 
  536                         connection = caseDb.getConnection();
 
  537                         statement = connection.createStatement();
 
  538                         rs = connection.executeQuery(statement, 
"SELECT attrs.artifact_id AS artifact_id, " 
  539                                         + 
"attrs.source AS source, attrs.context AS context, attrs.attribute_type_id AS attribute_type_id, " 
  540                                         + 
"attrs.value_type AS value_type, attrs.value_byte AS value_byte, " 
  541                                         + 
"attrs.value_text AS value_text, attrs.value_int32 AS value_int32, " 
  542                                         + 
"attrs.value_int64 AS value_int64, attrs.value_double AS value_double, " 
  543                                         + 
"types.type_name AS type_name, types.display_name AS display_name " 
  544                                         + 
"FROM blackboard_attributes AS attrs, blackboard_attribute_types AS types WHERE attrs.artifact_id IN (" + idString + 
") " 
  545                                         + 
" AND attrs.attribute_type_id = types.attribute_type_id" 
  546                                         + 
" ORDER BY " + rowId);
 
  548                                 final BlackboardAttribute attr = createAttributeFromResultSet(rs);
 
  549                                 attr.setParentDataSourceID(artifactMap.get(attr.getArtifactID()).getDataSourceObjectID());
 
  552                                 if (!attributeMap.containsKey(attr.getArtifactID())) {
 
  553                                         attributeMap.put(attr.getArtifactID(), 
new ArrayList<>());
 
  555                                 attributeMap.get(attr.getArtifactID()).add(attr);
 
  559                         for (Long artifactID : attributeMap.keySet()) {
 
  560                                 artifactMap.get(artifactID).setAttributes(attributeMap.get(artifactID));
 
  563                 } 
catch (SQLException ex) {
 
  564                         throw new TskCoreException(
"Error loading attributes", ex);
 
  567                         closeStatement(statement);
 
  568                         closeConnection(connection);
 
  581         private BlackboardAttribute createAttributeFromResultSet(ResultSet rs) 
throws SQLException {
 
  582                 int attributeTypeId = rs.getInt(
"attribute_type_id");
 
  583                 String attributeTypeName = rs.getString(
"type_name");
 
  584                 BlackboardAttribute.Type attributeType;
 
  585                 if (this.typeIdToAttributeTypeMap.containsKey(attributeTypeId)) {
 
  586                         attributeType = this.typeIdToAttributeTypeMap.get(attributeTypeId);
 
  588                         attributeType = 
new BlackboardAttribute.Type(attributeTypeId, attributeTypeName,
 
  589                                         rs.getString(
"display_name"),
 
  590                                         BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromType(rs.getInt(
"value_type")));
 
  591                         this.typeIdToAttributeTypeMap.put(attributeTypeId, attributeType);
 
  592                         this.typeNameToAttributeTypeMap.put(attributeTypeName, attributeType);
 
  595                 return new BlackboardAttribute(
 
  596                                 rs.getLong(
"artifact_id"),
 
  598                                 rs.getString(
"source"),
 
  599                                 rs.getString(
"context"),
 
  600                                 rs.getInt(
"value_int32"),
 
  601                                 rs.getLong(
"value_int64"),
 
  602                                 rs.getDouble(
"value_double"),
 
  603                                 rs.getString(
"value_text"),
 
  604                                 rs.getBytes(
"value_byte"), caseDb
 
  621                 try (CaseDbConnection connection = caseDb.getConnection()) {
 
  623                                 String updateString = 
"UPDATE tsk_file_attributes SET value_byte = ?, value_text = ?, value_int32 = ?, " 
  624                                         + 
" value_int64 = ?, value_double = ? WHERE attribute_type_id = " + attr.getAttributeType().getTypeID() 
 
  625                                         + 
" AND obj_id = " + fileObjId;
 
  627                                 try (PreparedStatement preparedStatement = connection.getPreparedStatement(updateString, Statement.NO_GENERATED_KEYS);) {
 
  628                                         preparedStatement.clearParameters();
 
  631                                                 preparedStatement.setBytes(1, attr.getValueBytes());
 
  633                                                 preparedStatement.setBytes(1, null);
 
  638                                                 preparedStatement.setString(2, attr.getValueString());
 
  640                                                 preparedStatement.setString(2, null);
 
  644                                                 preparedStatement.setInt(3, attr.getValueInt());
 
  646                                                 preparedStatement.setNull(3, java.sql.Types.INTEGER);
 
  651                                                 preparedStatement.setLong(4, attr.getValueLong());
 
  653                                                 preparedStatement.setNull(4, java.sql.Types.BIGINT);
 
  657                                                 preparedStatement.setDouble(5, attr.getValueDouble());
 
  659                                                 preparedStatement.setNull(5, java.sql.Types.DOUBLE);
 
  662                                         connection.executeUpdate(preparedStatement);
 
  664                                 } 
catch (SQLException ex) {
 
  665                                         throw new TskCoreException(String.format(
"Error updating attribute using query = '%s'", updateString), ex);
 
  683                 CaseDbConnection connection = null;
 
  684                 Statement statement = null;
 
  688                         connection = caseDb.getConnection();
 
  689                         statement = connection.createStatement();
 
  690                         rs = connection.executeQuery(statement, 
"SELECT attrs.id as id,  attrs.obj_id AS obj_id, " 
  691                                         + 
"attrs.attribute_type_id AS attribute_type_id, " 
  692                                         + 
"attrs.value_type AS value_type, attrs.value_byte AS value_byte, " 
  693                                         + 
"attrs.value_text AS value_text, attrs.value_int32 AS value_int32, " 
  694                                         + 
"attrs.value_int64 AS value_int64, attrs.value_double AS value_double, " 
  695                                         + 
"types.type_name AS type_name, types.display_name AS display_name " 
  696                                         + 
"FROM tsk_file_attributes AS attrs " 
  697                                         + 
" INNER JOIN blackboard_attribute_types AS types " 
  698                                         + 
" ON attrs.attribute_type_id = types.attribute_type_id " 
  699                                         + 
" WHERE attrs.obj_id = " + file.getId());
 
  701                         ArrayList<Attribute> attributes = 
new ArrayList<Attribute>();
 
  703                                 int attributeTypeId = rs.getInt(
"attribute_type_id");
 
  704                                 String attributeTypeName = rs.getString(
"type_name");
 
  706                                 if (this.typeIdToAttributeTypeMap.containsKey(attributeTypeId)) {
 
  707                                         attributeType = this.typeIdToAttributeTypeMap.get(attributeTypeId);
 
  709                                         attributeType = 
new BlackboardAttribute.Type(attributeTypeId, attributeTypeName,
 
  710                                                         rs.getString(
"display_name"),
 
  711                                                         BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromType(rs.getInt(
"value_type")));
 
  712                                         this.typeIdToAttributeTypeMap.put(attributeTypeId, attributeType);
 
  713                                         this.typeNameToAttributeTypeMap.put(attributeTypeName, attributeType);
 
  716                                 final Attribute attr = 
new Attribute(
 
  718                                                 rs.getLong(
"obj_id"),
 
  720                                                 rs.getInt(
"value_int32"),
 
  721                                                 rs.getLong(
"value_int64"),
 
  722                                                 rs.getDouble(
"value_double"),
 
  723                                                 rs.getString(
"value_text"),
 
  724                                                 rs.getBytes(
"value_byte"), caseDb
 
  726                                 attributes.add(attr);
 
  729                 } 
catch (SQLException ex) {
 
  730                         throw new TskCoreException(
"Error getting attributes for file, file id = " + file.getId(), ex);
 
  733                         closeStatement(statement);
 
  734                         closeConnection(connection);
 
  748         void initBlackboardArtifactTypes(CaseDbConnection connection) 
throws SQLException {
 
  750                 try (Statement statement = connection.createStatement()) {
 
  757                         ResultSet resultSet = connection.executeQuery(statement, 
"SELECT artifact_type_id, type_name, display_name, category_type FROM blackboard_artifact_types"); 
 
  758                         while (resultSet.next()) {
 
  759                                 BlackboardArtifact.Type type = 
new BlackboardArtifact.Type(resultSet.getInt(
"artifact_type_id"),
 
  760                                                 resultSet.getString(
"type_name"), resultSet.getString(
"display_name"),
 
  761                                                 BlackboardArtifact.Category.fromID(resultSet.getInt(
"category_type")));
 
  762                                 typeIdToArtifactTypeMap.put(type.getTypeID(), type);
 
  763                                 typeNameToArtifactTypeMap.put(type.getTypeName(), type);
 
  777                         for (BlackboardArtifact.ARTIFACT_TYPE type : BlackboardArtifact.ARTIFACT_TYPE.values()) {
 
  778                                 if (typeIdToArtifactTypeMap.containsKey(type.getTypeID())) {
 
  782                                         statement.execute(
"INSERT INTO blackboard_artifact_types (artifact_type_id, type_name, display_name, category_type) VALUES (" + type.getTypeID() + 
" , '" + type.getLabel() + 
"', '" + type.getDisplayName() + 
"' , " + type.getCategory().getID() + 
") ON CONFLICT DO NOTHING"); 
 
  784                                         statement.execute(
"INSERT OR IGNORE INTO blackboard_artifact_types (artifact_type_id, type_name, display_name, category_type) VALUES (" + type.getTypeID() + 
" , '" + type.getLabel() + 
"', '" + type.getDisplayName() + 
"' , " + type.getCategory().getID() + 
")"); 
 
  786                                 typeIdToArtifactTypeMap.put(type.getTypeID(), 
new BlackboardArtifact.Type(type));
 
  787                                 typeNameToArtifactTypeMap.put(type.getLabel(), 
new BlackboardArtifact.Type(type));
 
  790                                 int newPrimaryKeyIndex = Collections.max(Arrays.asList(BlackboardArtifact.ARTIFACT_TYPE.values())).getTypeID() + 1;
 
  791                                 statement.execute(
"ALTER SEQUENCE blackboard_artifact_types_artifact_type_id_seq RESTART WITH " + newPrimaryKeyIndex); 
 
  807         void initBlackboardAttributeTypes(CaseDbConnection connection) 
throws SQLException {
 
  809                 try (Statement statement = connection.createStatement()) {
 
  816                         ResultSet resultSet = connection.executeQuery(statement, 
"SELECT attribute_type_id, type_name, display_name, value_type FROM blackboard_attribute_types"); 
 
  817                         while (resultSet.next()) {
 
  818                                 BlackboardAttribute.Type type = 
new BlackboardAttribute.Type(resultSet.getInt(
"attribute_type_id"),
 
  819                                                 resultSet.getString(
"type_name"), resultSet.getString(
"display_name"),
 
  820                                                 BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromType(resultSet.getLong(
"value_type")));
 
  821                                 typeIdToAttributeTypeMap.put(type.getTypeID(), type);
 
  822                                 typeNameToAttributeTypeMap.put(type.getTypeName(), type);
 
  836                         for (BlackboardAttribute.ATTRIBUTE_TYPE type : BlackboardAttribute.ATTRIBUTE_TYPE.values()) {
 
  837                                 if (typeIdToAttributeTypeMap.containsKey(type.getTypeID())) {
 
  841                                         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"); 
 
  843                                         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() + 
"')"); 
 
  845                                 typeIdToAttributeTypeMap.put(type.getTypeID(), 
new BlackboardAttribute.Type(type));
 
  846                                 typeNameToAttributeTypeMap.put(type.getLabel(), 
new BlackboardAttribute.Type(type));
 
  849                                 int newPrimaryKeyIndex = Collections.max(Arrays.asList(BlackboardAttribute.ATTRIBUTE_TYPE.values())).getTypeID() + 1;
 
  850                                 statement.execute(
"ALTER SEQUENCE blackboard_attribute_types_attribute_type_id_seq RESTART WITH " + newPrimaryKeyIndex); 
 
  880                         String conclusion, String configuration, String justification, Collection<BlackboardAttribute> attributesList)
 
  884                         throw new BlackboardException(String.format(
"Artifact type (name = %s) is not of Analysis Result category. ", artifactType.getTypeName()));
 
  890                                         conclusion, configuration, justification, attributesList, transaction);
 
  892                         return analysisResult;
 
  897                                 LOGGER.log(Level.SEVERE, 
"Failed to rollback transaction after exception. " 
  898                                                 + 
"Error invoking newAnalysisResult with dataSourceObjId: " 
  899                                                 + (dataSourceObjId == null ? 
"<null>" : dataSourceObjId)
 
  900                                                 + 
",  sourceObjId: " + objId, ex2);
 
  929                         String conclusion, String configuration, String justification, Collection<BlackboardAttribute> attributesList, 
CaseDbTransaction transaction) 
throws BlackboardException {
 
  932                         throw new BlackboardException(String.format(
"Artifact type (name = %s) is not of Analysis Result category. ", artifactType.getTypeName()));
 
  937                         AnalysisResult analysisResult = caseDb.newAnalysisResult(artifactType, objId, dataSourceObjId, score, conclusion, configuration, justification, transaction.getConnection());
 
  940                         if (attributesList != null && !attributesList.isEmpty()) {
 
  945                         Score aggregateScore = caseDb.
getScoringManager().updateAggregateScoreAfterAddition(objId, dataSourceObjId, analysisResult.
getScore(), transaction);
 
  951                         throw new BlackboardException(
"Failed to add analysis result.", ex);
 
  979                         if (transaction != null) {
 
 1000                 List<AnalysisResult> analysisResults = 
getAnalysisResultsWhere(
" artifacts.artifact_obj_id = " + artifactObjId, transaction.getConnection());
 
 1002                 if (analysisResults.isEmpty()) {
 
 1003                         throw new TskCoreException(String.format(
"Analysis Result not found for artifact obj id %d", artifactObjId));
 
 1025                         CaseDbConnection connection = transaction.getConnection();
 
 1028                         String deleteSQL = 
"DELETE FROM blackboard_artifacts WHERE artifact_obj_id = ?";
 
 1030                         PreparedStatement deleteStatement = connection.getPreparedStatement(deleteSQL, Statement.RETURN_GENERATED_KEYS);
 
 1031                         deleteStatement.clearParameters();
 
 1032                         deleteStatement.setLong(1, analysisResult.getId());
 
 1034                         deleteStatement.executeUpdate();
 
 1037                         transaction.registerDeletedAnalysisResult(analysisResult.getObjectID());
 
 1039                         return caseDb.
getScoringManager().updateAggregateScoreAfterDeletion(analysisResult.getObjectID(), analysisResult.getDataSourceObjectID(), transaction);
 
 1041                 } 
catch (SQLException ex) {
 
 1042                         throw new TskCoreException(String.format(
"Error deleting analysis result with artifact obj id %d", analysisResult.getId()), ex);
 
 1046         private final static String ANALYSIS_RESULT_QUERY_STRING_GENERIC = 
"SELECT DISTINCT artifacts.artifact_id AS artifact_id, "  
 1047                         + 
" 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, " 
 1048                         + 
" types.type_name AS type_name, types.display_name AS display_name, types.category_type as category_type," 
 1049                         + 
" artifacts.review_status_id AS review_status_id, "  
 1050                         + 
" results.conclusion AS conclusion,  results.significance AS significance,  results.priority AS priority,  " 
 1051                         + 
" results.configuration AS configuration,  results.justification AS justification " 
 1052                         + 
" FROM blackboard_artifacts AS artifacts " 
 1053                         + 
" JOIN blackboard_artifact_types AS types "  
 1054                         + 
"             ON artifacts.artifact_type_id = types.artifact_type_id"  
 1055                         + 
" LEFT JOIN tsk_analysis_results AS results " 
 1056                         + 
"             ON artifacts.artifact_obj_id = results.artifact_obj_id "; 
 
 1058         private final static String ANALYSIS_RESULT_QUERY_STRING_WITH_ATTRIBUTES
 
 1059                         = ANALYSIS_RESULT_QUERY_STRING_GENERIC
 
 1060                         + 
" JOIN blackboard_attributes AS attributes "  
 1061                         + 
" ON artifacts.artifact_id = attributes.artifact_id "  
 1062                         + 
" WHERE types.category_type = " + BlackboardArtifact.Category.ANALYSIS_RESULT.getID(); 
 
 1064         private final static String ANALYSIS_RESULT_QUERY_STRING_WHERE
 
 1065                         = ANALYSIS_RESULT_QUERY_STRING_GENERIC
 
 1066                         + 
" WHERE artifacts.review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID() 
 
 1067                         + 
"     AND types.category_type = " + BlackboardArtifact.Category.ANALYSIS_RESULT.getID(); 
 
 1095                 return getAnalysisResultsWhere(
" artifacts.artifact_type_id = " + artifactTypeId + 
" AND artifacts.data_source_obj_id = " + dataSourceObjId);
 
 1113                 try (CaseDbConnection connection = caseDb.getConnection()) {
 
 1114                         String whereClause = 
" artifacts.data_source_obj_id = " + dataSourceObjId;
 
 1115                         if (artifactTypeID != null) {
 
 1116                                 whereClause += 
" AND artifacts.artifact_type_id = " + artifactTypeID;
 
 1148         List<DataArtifact> getDataArtifactsBySource(
long sourceObjId) 
throws TskCoreException {
 
 1150                 try (CaseDbConnection connection = caseDb.getConnection()) {
 
 1197                 String queryString = 
"SELECT COUNT(*) AS count "  
 1198                                 + 
" FROM blackboard_artifacts AS arts " 
 1199                                 + 
" JOIN blackboard_artifact_types AS types "  
 1200                                 + 
"             ON arts.artifact_type_id = types.artifact_type_id"  
 1201                                 + 
" WHERE types.category_type = " + category.getID()
 
 1202                                 + 
" AND arts.obj_id = " + sourceObjId;
 
 1206                                 Statement statement = connection.createStatement();
 
 1207                                 ResultSet resultSet = connection.executeQuery(statement, queryString);) {
 
 1208                         if (resultSet.next()) {
 
 1209                                 return resultSet.getLong(
"count") > 0;
 
 1212                 } 
catch (SQLException ex) {
 
 1213                         throw new TskCoreException(
"Error getting artifact types is use for data source." + ex.getMessage(), ex);
 
 1231         List<AnalysisResult> 
getAnalysisResults(
long sourceObjId, CaseDbConnection connection) 
throws TskCoreException {
 
 1250                         throw new TskCoreException(String.format(
"Artifact type id %d is not in analysis result catgeory.", artifactTypeId));
 
 1253                 String whereClause = 
" types.artifact_type_id = " + artifactTypeId
 
 1254                                 + 
" AND artifacts.obj_id = " + sourceObjId;
 
 1271                 try (CaseDbConnection connection = caseDb.getConnection()) {
 
 1292                 final String queryString = ANALYSIS_RESULT_QUERY_STRING_WHERE
 
 1293                                 + 
" AND " + whereClause;
 
 1295                 try (Statement statement = connection.createStatement();
 
 1296                                 ResultSet resultSet = connection.executeQuery(statement, queryString);) {
 
 1298                         List<AnalysisResult> analysisResults = resultSetToAnalysisResults(resultSet);
 
 1299                         return analysisResults;
 
 1300                 } 
catch (SQLException ex) {
 
 1301                         throw new TskCoreException(String.format(
"Error getting analysis results for WHERE clause = '%s'", whereClause), ex);
 
 1316                 String whereClause = 
" artifacts.artifact_obj_id = " + artifactObjId;
 
 1319                 if (results.isEmpty()) { 
 
 1320                         throw new TskCoreException(String.format(
"Error getting analysis result with id = '%d'", artifactObjId));
 
 1322                 if (results.size() > 1) { 
 
 1323                         throw new TskCoreException(String.format(
"Multiple analysis results found with id = '%d'", artifactObjId));
 
 1326                 return results.get(0);
 
 1344         private List<AnalysisResult> resultSetToAnalysisResults(ResultSet resultSet) 
throws SQLException, 
TskCoreException {
 
 1345                 ArrayList<AnalysisResult> analysisResults = 
new ArrayList<>();
 
 1347                 while (resultSet.next()) {
 
 1348                         analysisResults.add(
new AnalysisResult(caseDb, resultSet.getLong(
"artifact_id"), resultSet.getLong(
"obj_id"),
 
 1349                                         resultSet.getLong(
"artifact_obj_id"),
 
 1350                                         resultSet.getObject(
"data_source_obj_id") != null ? resultSet.getLong(
"data_source_obj_id") : null,
 
 1351                                         resultSet.getInt(
"artifact_type_id"), resultSet.getString(
"type_name"), resultSet.getString(
"display_name"),
 
 1354                                         resultSet.getString(
"conclusion"), resultSet.getString(
"configuration"), resultSet.getString(
"justification")));
 
 1357                 return analysisResults;
 
 1360         private final static String DATA_ARTIFACT_QUERY_STRING_GENERIC = 
"SELECT DISTINCT artifacts.artifact_id AS artifact_id, "  
 1361                         + 
"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, "  
 1362                         + 
" types.type_name AS type_name, types.display_name AS display_name, types.category_type as category_type," 
 1363                         + 
" artifacts.review_status_id AS review_status_id, "  
 1364                         + 
" data_artifacts.os_account_obj_id as os_account_obj_id "  
 1365                         + 
" FROM blackboard_artifacts AS artifacts "  
 1366                         + 
" JOIN blackboard_artifact_types AS types "  
 1367                         + 
"             ON artifacts.artifact_type_id = types.artifact_type_id"  
 1368                         + 
" LEFT JOIN tsk_data_artifacts AS data_artifacts "  
 1369                         + 
"             ON artifacts.artifact_obj_id = data_artifacts.artifact_obj_id "; 
 
 1371         private final static String DATA_ARTIFACT_QUERY_STRING_WITH_ATTRIBUTES
 
 1372                         = DATA_ARTIFACT_QUERY_STRING_GENERIC
 
 1373                         + 
" JOIN blackboard_attributes AS attributes "  
 1374                         + 
" ON artifacts.artifact_id = attributes.artifact_id "  
 1375                         + 
" WHERE types.category_type = " + BlackboardArtifact.Category.DATA_ARTIFACT.getID(); 
 
 1377         private final static String DATA_ARTIFACT_QUERY_STRING_WHERE
 
 1378                         = DATA_ARTIFACT_QUERY_STRING_GENERIC
 
 1379                         + 
" WHERE artifacts.review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID() 
 
 1380                         + 
"     AND types.category_type = " + BlackboardArtifact.Category.DATA_ARTIFACT.getID(); 
 
 1396                 try (CaseDbConnection connection = caseDb.getConnection()) {
 
 1397                         String whereClause = 
" artifacts.data_source_obj_id = " + dataSourceObjId;
 
 1398                         if (artifactTypeID != null) {
 
 1399                                 whereClause += 
" AND artifacts.artifact_type_id = " + artifactTypeID;
 
 1423                         throw new TskCoreException(String.format(
"Artifact type id %d is not in data artifact catgeory.", artifactTypeID));
 
 1427                 try (CaseDbConnection connection = caseDb.getConnection()) {
 
 1428                         String whereClause = 
"artifacts.data_source_obj_id = " + dataSourceObjId
 
 1429                                         + 
" AND artifacts.artifact_type_id = " + artifactTypeID;
 
 1451                         throw new TskCoreException(String.format(
"Artifact type id %d is not in data artifact catgeory.", artifactTypeID));
 
 1455                 try (CaseDbConnection connection = caseDb.getConnection()) {
 
 1456                         String whereClause = 
" artifacts.artifact_type_id = " + artifactTypeID;
 
 1476                 try (CaseDbConnection connection = caseDb.getConnection()) {
 
 1477                         String whereClause = 
" artifacts.artifact_obj_id = " + artifactObjId;
 
 1480                         if (artifacts.isEmpty()) { 
 
 1481                                 throw new TskCoreException(String.format(
"Error getting data artifact with id = '%d'", artifactObjId));
 
 1483                         if (artifacts.size() > 1) { 
 
 1484                                 throw new TskCoreException(String.format(
"Multiple data artifacts found with id = '%d'", artifactObjId));
 
 1487                         return artifacts.get(0);
 
 1505                 try (CaseDbConnection connection = caseDb.getConnection()) {
 
 1526                 final String queryString = DATA_ARTIFACT_QUERY_STRING_WHERE
 
 1527                                 + 
" AND " + whereClause + 
" ";
 
 1529                 try (Statement statement = connection.createStatement();
 
 1530                                 ResultSet resultSet = connection.executeQuery(statement, queryString);) {
 
 1532                         List<DataArtifact> dataArtifacts = resultSetToDataArtifacts(resultSet);
 
 1533                         return dataArtifacts;
 
 1534                 } 
catch (SQLException ex) {
 
 1535                         throw new TskCoreException(String.format(
"Error getting data artifacts with queryString = %s", queryString), ex);
 
 1554         private List<DataArtifact> resultSetToDataArtifacts(ResultSet resultSet) 
throws SQLException, TskCoreException {
 
 1555                 ArrayList<DataArtifact> dataArtifacts = 
new ArrayList<>();
 
 1557                 while (resultSet.next()) {
 
 1559                         Long osAccountObjId = resultSet.getLong(
"os_account_obj_id");
 
 1560                         if (resultSet.wasNull()) {
 
 1561                                 osAccountObjId = null;
 
 1564                         dataArtifacts.add(
new DataArtifact(caseDb, resultSet.getLong(
"artifact_id"), resultSet.getLong(
"obj_id"),
 
 1565                                         resultSet.getLong(
"artifact_obj_id"),
 
 1566                                         resultSet.getObject(
"data_source_obj_id") != null ? resultSet.getLong(
"data_source_obj_id") : null,
 
 1567                                         resultSet.getInt(
"artifact_type_id"), resultSet.getString(
"type_name"), resultSet.getString(
"display_name"),
 
 1568                                         BlackboardArtifact.ReviewStatus.withID(resultSet.getInt(
"review_status_id")), osAccountObjId, 
false));
 
 1571                 return dataArtifacts;
 
 1593                 if (typeNameToAttributeTypeMap.containsKey(typeName)) {
 
 1594                         return typeNameToAttributeTypeMap.get(typeName);
 
 1600                         String matchingAttrQuery = 
"SELECT attribute_type_id, type_name, display_name, value_type " 
 1601                                         + 
"FROM blackboard_attribute_types WHERE type_name = ?";
 
 1603                         PreparedStatement query = trans.getConnection().getPreparedStatement(matchingAttrQuery, Statement.RETURN_GENERATED_KEYS);
 
 1604                         query.clearParameters();
 
 1605                         query.setString(1, typeName);
 
 1606                         try (ResultSet rs = query.executeQuery()) {
 
 1612                                                         rs.getInt(
"attribute_type_id"),
 
 1613                                                         rs.getString(
"type_name"),
 
 1614                                                         rs.getString(
"display_name"),
 
 1618                                         this.typeIdToAttributeTypeMap.put(foundType.getTypeID(), foundType);
 
 1619                                         this.typeNameToAttributeTypeMap.put(foundType.getTypeName(), foundType);
 
 1626                         String insertStatement = 
"INSERT INTO blackboard_attribute_types (attribute_type_id, type_name, display_name, value_type) VALUES (\n" 
 1628                                         + 
"(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" 
 1632                         PreparedStatement insertPreparedStatement = trans.getConnection().getPreparedStatement(insertStatement, Statement.RETURN_GENERATED_KEYS);
 
 1633                         insertPreparedStatement.clearParameters();
 
 1634                         insertPreparedStatement.setString(1, typeName);
 
 1635                         insertPreparedStatement.setString(2, displayName);
 
 1636                         insertPreparedStatement.setLong(3, valueType.getType());
 
 1638                         int numUpdated = insertPreparedStatement.executeUpdate();
 
 1641                         Integer attrId = null;
 
 1643                         if (numUpdated > 0) {
 
 1644                                 try (ResultSet insertResult = insertPreparedStatement.getGeneratedKeys()) {
 
 1645                                         if (insertResult.next()) {
 
 1646                                                 attrId = insertResult.getInt(1);
 
 1651                         if (attrId == null) {
 
 1652                                 throw new BlackboardException(MessageFormat.format(
 
 1653                                                 "Error adding attribute type.  Item with name {0} was not inserted successfully into the database.", typeName));
 
 1660                         this.typeIdToAttributeTypeMap.put(type.getTypeID(), type);
 
 1661                         this.typeNameToAttributeTypeMap.put(type.getTypeName(), type);
 
 1664                         throw new BlackboardException(
"Error adding attribute type: " + typeName, ex);
 
 1667                                 if (trans != null) {
 
 1672                                 LOGGER.log(Level.SEVERE, 
"Error rolling back transaction", ex2);
 
 1690                 final String queryString = 
"SELECT DISTINCT arts.artifact_type_id AS artifact_type_id, " 
 1691                                 + 
"types.type_name AS type_name, " 
 1692                                 + 
"types.display_name AS display_name, " 
 1693                                 + 
"types.category_type AS category_type " 
 1694                                 + 
"FROM blackboard_artifact_types AS types " 
 1695                                 + 
"INNER JOIN blackboard_artifacts AS arts " 
 1696                                 + 
"ON arts.artifact_type_id = types.artifact_type_id " 
 1697                                 + 
"WHERE arts.data_source_obj_id = " + dataSourceObjId;
 
 1701                                 Statement statement = connection.createStatement();
 
 1702                                 ResultSet resultSet = connection.executeQuery(statement, queryString);) {
 
 1705                         while (resultSet.next()) {
 
 1707                                                 resultSet.getString(
"type_name"), resultSet.getString(
"display_name"),
 
 1710                         return uniqueArtifactTypes;
 
 1711                 } 
catch (SQLException ex) {
 
 1712                         throw new TskCoreException(
"Error getting artifact types is use for data source." + ex.getMessage(), ex);
 
 1731                 return getArtifactsCountHelper(artifactTypeID,
 
 1732                                 "blackboard_artifacts.data_source_obj_id = '" + dataSourceObjId + 
"';");
 
 1747                 return getArtifactsCountHelper(artifactTypeID, null);
 
 1763                 String whereClause = String.format(
"artifacts.data_source_obj_id = %d", dataSourceObjId);
 
 1764                 return getArtifactsWhere(
getArtifactType(artifactTypeID), whereClause);
 
 1779         public List<BlackboardArtifact> 
getArtifacts(Collection<BlackboardArtifact.Type> artifactTypes,
 
 1782                 if (artifactTypes.isEmpty() || dataSourceObjIds.isEmpty()) {
 
 1783                         return new ArrayList<>();
 
 1786                 String analysisResultQuery = 
"";
 
 1787                 String dataArtifactQuery = 
"";
 
 1791                                 if (!analysisResultQuery.isEmpty()) {
 
 1792                                         analysisResultQuery += 
" OR ";
 
 1794                                 analysisResultQuery += 
"types.artifact_type_id = " + type.getTypeID();
 
 1796                                 if (!dataArtifactQuery.isEmpty()) {
 
 1797                                         dataArtifactQuery += 
" OR ";
 
 1799                                 dataArtifactQuery += 
"types.artifact_type_id = " + type.getTypeID();
 
 1803                 String dsQuery = 
"";
 
 1804                 for (
long dsId : dataSourceObjIds) {
 
 1805                         if (!dsQuery.isEmpty()) {
 
 1808                         dsQuery += 
"artifacts.data_source_obj_id = " + dsId;
 
 1811                 List<BlackboardArtifact> artifacts = 
new ArrayList<>();
 
 1813                 if (!analysisResultQuery.isEmpty()) {
 
 1814                         String fullQuery = 
"( " + analysisResultQuery + 
" ) AND (" + dsQuery + 
") ";
 
 1818                 if (!dataArtifactQuery.isEmpty()) {
 
 1819                         String fullQuery = 
"( " + dataArtifactQuery + 
" ) AND (" + dsQuery + 
") ";
 
 1846                 String query = 
" AND artifacts.artifact_type_id = " + artifactType.getTypeID() 
 
 1847                                 + 
" AND attributes.attribute_type_id = " + attributeType.getTypeID() 
 
 1848                                 + ((value == null || value.isEmpty()) ? 
"" : 
" AND attributes.value_text = '" + value + 
"'") 
 
 1850                                 + (dataSourceObjId != null ? 
" AND artifacts.data_source_obj_id = " + dataSourceObjId : 
""); 
 
 1852                 List<BlackboardArtifact> artifacts = 
new ArrayList<>();
 
 1856                                 ? ANALYSIS_RESULT_QUERY_STRING_WITH_ATTRIBUTES + query
 
 1857                                 : DATA_ARTIFACT_QUERY_STRING_WITH_ATTRIBUTES + query);
 
 1859                 try (CaseDbConnection connection = caseDb.getConnection()) {
 
 1860                         try (Statement statement = connection.createStatement();
 
 1861                                         ResultSet resultSet = connection.executeQuery(statement, finalQuery);) {
 
 1864                                         artifacts.addAll(resultSetToAnalysisResults(resultSet));
 
 1866                                         artifacts.addAll(resultSetToDataArtifacts(resultSet));
 
 1868                         } 
catch (SQLException ex) {
 
 1869                                 throw new TskCoreException(String.format(
"Error getting results with queryString = '%s'", finalQuery), ex);
 
 1929                 String dataSourceClause = dataSourceId == null
 
 1931                                 : 
" AND artifacts.data_source_obj_id = ? "; 
 
 1933                 String kwsListClause = (kwsListName == null || kwsListName.isEmpty()
 
 1934                                 ? 
" WHERE r.set_name IS NULL " 
 1935                                 : 
" WHERE r.set_name = ? ");
 
 1937                 String keywordClause = (keyword == null || keyword.isEmpty()
 
 1939                                 : 
" AND r.keyword = ? ");
 
 1941                 String searchTypeClause = (searchType == null
 
 1943                                 : 
" AND r.search_type = ? ");
 
 1945                 String regexClause = (regex == null || regex.isEmpty()
 
 1947                                 : 
" AND r.regexp_str = ? ");
 
 1949                 String query = 
"SELECT r.* FROM ( " 
 1950                                 + 
" SELECT DISTINCT artifacts.artifact_id AS artifact_id, " 
 1951                                 + 
" artifacts.obj_id AS obj_id, " 
 1952                                 + 
" artifacts.artifact_obj_id AS artifact_obj_id, " 
 1953                                 + 
" artifacts.data_source_obj_id AS data_source_obj_id, " 
 1954                                 + 
" artifacts.artifact_type_id AS artifact_type_id, " 
 1955                                 + 
" types.type_name AS type_name, " 
 1956                                 + 
" types.display_name AS display_name, " 
 1957                                 + 
" types.category_type as category_type," 
 1958                                 + 
" artifacts.review_status_id AS review_status_id, " 
 1959                                 + 
" results.conclusion AS conclusion, " 
 1960                                 + 
" results.significance AS significance, " 
 1961                                 + 
" results.priority AS priority, " 
 1962                                 + 
" results.configuration AS configuration, " 
 1963                                 + 
" results.justification AS justification, " 
 1964                                 + 
" (SELECT value_text FROM blackboard_attributes attr WHERE attr.artifact_id = artifacts.artifact_id AND attr.attribute_type_id = " 
 1966                                 + 
" (SELECT value_int32 FROM blackboard_attributes attr WHERE attr.artifact_id = artifacts.artifact_id AND attr.attribute_type_id = " 
 1968                                 + 
" (SELECT value_text FROM blackboard_attributes attr WHERE attr.artifact_id = artifacts.artifact_id AND attr.attribute_type_id = " 
 1970                                 + 
" (SELECT value_text FROM blackboard_attributes attr WHERE attr.artifact_id = artifacts.artifact_id AND attr.attribute_type_id = " 
 1972                                 + 
" FROM blackboard_artifacts artifacts " 
 1973                                 + 
" JOIN blackboard_artifact_types AS types " 
 1974                                 + 
" ON artifacts.artifact_type_id = types.artifact_type_id " 
 1975                                 + 
" LEFT JOIN tsk_analysis_results AS results " 
 1976                                 + 
" ON artifacts.artifact_obj_id = results.artifact_obj_id " 
 1979                                 + dataSourceClause + 
" ) r " 
 1985                 List<BlackboardArtifact> artifacts = 
new ArrayList<>();
 
 1987                 try (CaseDbConnection connection = caseDb.getConnection()) {
 
 1990                                 PreparedStatement preparedStatement = connection.getPreparedStatement(query, Statement.RETURN_GENERATED_KEYS);
 
 1991                                 preparedStatement.clearParameters();
 
 1993                                 if (dataSourceId != null) {
 
 1994                                         preparedStatement.setLong(++paramIdx, dataSourceId);
 
 1997                                 if (!(kwsListName == null || kwsListName.isEmpty())) {
 
 1998                                         preparedStatement.setString(++paramIdx, kwsListName);
 
 2001                                 if (!(keyword == null || keyword.isEmpty())) {
 
 2002                                         preparedStatement.setString(++paramIdx, keyword);
 
 2005                                 if (searchType != null) {
 
 2006                                         preparedStatement.setInt(++paramIdx, searchType.getType());
 
 2009                                 if (!(regex == null || regex.isEmpty())) {
 
 2010                                         preparedStatement.setString(++paramIdx, regex);
 
 2013                                 try (ResultSet resultSet = connection.executeQuery(preparedStatement)) {
 
 2014                                         artifacts.addAll(resultSetToAnalysisResults(resultSet));
 
 2017                         } 
catch (SQLException ex) {
 
 2018                                 throw new TskCoreException(String.format(
"Error getting keyword search results with queryString = '%s'", query), ex);
 
 2039         private long getArtifactsCountHelper(
int artifactTypeID, String whereClause) 
throws TskCoreException {
 
 2040                 String queryString = 
"SELECT COUNT(*) AS count FROM blackboard_artifacts " 
 2041                                 + 
"WHERE blackboard_artifacts.artifact_type_id = " + artifactTypeID
 
 2044                 if (whereClause != null) {
 
 2045                         queryString += 
" AND " + whereClause;
 
 2049                 try (SleuthkitCase.CaseDbConnection connection = caseDb.getConnection();
 
 2050                                 Statement statement = connection.createStatement();
 
 2051                                 ResultSet resultSet = connection.executeQuery(statement, queryString);) {
 
 2053                         if (resultSet.next()) {
 
 2054                                 count = resultSet.getLong(
"count");
 
 2057                 } 
catch (SQLException ex) {
 
 2058                         throw new TskCoreException(
"Error getting artifact types is use for data source." + ex.getMessage(), ex);
 
 2078                 List<BlackboardArtifact> existingArtifacts = content.getArtifacts(artifactType.getTypeID());
 
 2080                         if (attributesMatch(artifact.getAttributes(), attributes)) {
 
 2116         private boolean attributesMatch(Collection<BlackboardAttribute> fileAttributesList, Collection<BlackboardAttribute> expectedAttributesList) {
 
 2118                         boolean match = 
false;
 
 2121                                 if (attributeType.getTypeID() != expectedAttribute.getAttributeType().getTypeID()) {
 
 2125                                 Object fileAttributeValue;
 
 2126                                 Object expectedAttributeValue;
 
 2127                                 switch (attributeType.getValueType()) {
 
 2129                                                 fileAttributeValue = fileAttribute.getValueBytes();
 
 2130                                                 expectedAttributeValue = expectedAttribute.getValueBytes();
 
 2133                                                 fileAttributeValue = fileAttribute.getValueDouble();
 
 2134                                                 expectedAttributeValue = expectedAttribute.getValueDouble();
 
 2137                                                 fileAttributeValue = fileAttribute.getValueInt();
 
 2138                                                 expectedAttributeValue = expectedAttribute.getValueInt();
 
 2142                                                 fileAttributeValue = fileAttribute.getValueLong();
 
 2143                                                 expectedAttributeValue = expectedAttribute.getValueLong();
 
 2147                                                 fileAttributeValue = fileAttribute.getValueString();
 
 2148                                                 expectedAttributeValue = expectedAttribute.getValueString();
 
 2151                                                 fileAttributeValue = fileAttribute.getDisplayString();
 
 2152                                                 expectedAttributeValue = expectedAttribute.getDisplayString();
 
 2160                                 if (fileAttributeValue instanceof byte[]) {
 
 2161                                         if (Arrays.equals((byte[]) fileAttributeValue, (byte[]) expectedAttributeValue)) {
 
 2165                                 } 
else if (fileAttributeValue.equals(expectedAttributeValue)) {
 
 2189         public static final class BlackboardException 
extends Exception {
 
 2191                 private static final long serialVersionUID = 1L;
 
 2198                 BlackboardException(String message) {
 
 2209                 BlackboardException(String message, Throwable cause) {
 
 2210                         super(message, cause);
 
 2231                         Collection<BlackboardAttribute> attributes, Long osAccountId) 
throws TskCoreException {
 
 2234                         throw new TskCoreException(String.format(
"Artifact type (name = %s) is not of Data Artifact category. ", artifactType.getTypeName()));
 
 2240                                         attributes, osAccountId, transaction);
 
 2242                         return dataArtifact;
 
 2247                                 LOGGER.log(Level.SEVERE, 
"Failed to rollback transaction after exception. " 
 2248                                                 + 
"Error invoking newDataArtifact with dataSourceObjId: " + dataSourceObjId + 
",  sourceObjId: " + sourceObjId, ex2);
 
 2305                         Collection<BlackboardAttribute> attributes,
 
 2310                         throw new TskCoreException(String.format(
"Artifact type (name = %s) is not of Data Artifact category. ", artifactType.getTypeName()));
 
 2314                         CaseDbConnection connection = transaction.getConnection();
 
 2316                         PreparedStatement statement = caseDb.createInsertArtifactStatement(artifactType.getTypeID(), sourceObjId, artifact_obj_id, dataSourceObjId, connection);
 
 2318                         connection.executeUpdate(statement);
 
 2319                         try (ResultSet resultSet = statement.getGeneratedKeys()) {
 
 2322                                                 sourceObjId, artifact_obj_id, dataSourceObjId, artifactType.getTypeID(),
 
 2324                                                 osAccountObjId, 
true);
 
 2327                                 if (osAccountObjId != null) {
 
 2328                                         String insertDataArtifactSQL = 
"INSERT INTO tsk_data_artifacts (artifact_obj_id, os_account_obj_id) VALUES (?, ?)";
 
 2330                                         statement = connection.getPreparedStatement(insertDataArtifactSQL, Statement.NO_GENERATED_KEYS);
 
 2331                                         statement.clearParameters();
 
 2333                                         statement.setLong(1, artifact_obj_id);
 
 2334                                         statement.setLong(2, osAccountObjId);
 
 2335                                         connection.executeUpdate(statement);
 
 2338                                         if (Objects.nonNull(osAccountInstanceType)) {
 
 2344                                 if (Objects.nonNull(attributes) && !attributes.isEmpty()) {
 
 2348                                 return dataArtifact;
 
 2350                 } 
catch (SQLException ex) {
 
 2351                         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);
 
 2367                 String whereClause = String.format(
"artifacts.obj_id = %d", sourceObjId);
 
 2368                 return getArtifactsWhere(artifactType, whereClause);
 
 2380         List<BlackboardArtifact> getArtifactsByType(BlackboardArtifact.Type artifactType) throws TskCoreException {
 
 2381                 List<BlackboardArtifact> artifacts = 
new ArrayList<>();
 
 2382                 if (artifactType.getCategory() == BlackboardArtifact.Category.ANALYSIS_RESULT) {
 
 2407         private List<BlackboardArtifact> getArtifactsWhere(BlackboardArtifact.Type artifactType, String whereClause) 
throws TskCoreException {
 
 2408                 List<BlackboardArtifact> artifacts = 
new ArrayList<>();
 
 2409                 String whereWithType = whereClause + 
" AND artifacts.artifact_type_id = " + artifactType.getTypeID();
 
 2411                 if (artifactType.getCategory() == BlackboardArtifact.Category.ANALYSIS_RESULT) {
 
 2427                 private final String moduleName;
 
 2429                 private final ImmutableSet<BlackboardArtifact> artifacts;
 
 2430                 private final Long ingestJobId;
 
 2443                 private ArtifactsPostedEvent(Collection<BlackboardArtifact> artifacts, String moduleName, Long ingestJobId) 
throws BlackboardException {
 
 2444                         Set<Integer> typeIDS = artifacts.stream()
 
 2446                                         .collect(Collectors.toSet());
 
 2448                         for (Integer typeID : typeIDS) {
 
 2451                                 } 
catch (TskCoreException tskCoreException) {
 
 2452                                         throw new BlackboardException(
"Error getting artifact type by id.", tskCoreException);
 
 2455                         artifactTypes = ImmutableSet.copyOf(types);
 
 2456                         this.artifacts = ImmutableSet.copyOf(artifacts);
 
 2457                         this.moduleName = moduleName;
 
 2458                         this.ingestJobId = ingestJobId;
 
 2467                         return ImmutableSet.copyOf(artifacts);
 
 2478                         Set<BlackboardArtifact> tempSet = artifacts.stream()
 
 2479                                         .filter(artifact -> artifact.getArtifactTypeID() == artifactType.getTypeID())
 
 2480                                         .collect(Collectors.toSet());
 
 2481                         return ImmutableSet.copyOf(tempSet);
 
 2499                         return ImmutableSet.copyOf(artifactTypes);
 
 2509                         return Optional.ofNullable(ingestJobId);
 
static Priority fromID(int id)
 
List< BlackboardArtifact > getArtifacts(Collection< BlackboardArtifact.Type > artifactTypes, Collection< Long > dataSourceObjIds)
 
static Significance fromID(int id)
 
AnalysisResult getAnalysisResultById(long artifactObjId)
 
void postArtifact(BlackboardArtifact artifact, String moduleName)
 
CaseDbTransaction beginTransaction()
 
List< DataArtifact > getDataArtifacts(int artifactTypeID, long dataSourceObjId)
 
List< DataArtifact > getDataArtifacts(long dataSourceObjId, Integer artifactTypeID)
 
boolean hasAnalysisResults(long sourceObjId)
 
void postArtifacts(Collection< BlackboardArtifact > artifacts, String moduleName)
 
static final Type TSK_KEYWORD_HIT
 
static Category fromID(int id)
 
void addAttributes(Collection< BlackboardAttribute > attributes)
 
DataArtifact newDataArtifact(BlackboardArtifact.Type artifactType, long sourceObjId, Long dataSourceObjId, Collection< BlackboardAttribute > attributes, Long osAccountId)
 
ArrayList< BlackboardAttribute > getBlackboardAttributes(final BlackboardArtifact artifact)
 
DataArtifact getDataArtifactById(long artifactObjId)
 
Collection< BlackboardArtifact > getArtifacts()
 
BlackboardArtifact.Type getOrAddArtifactType(String typeName, String displayName, BlackboardArtifact.Category category)
 
Score deleteAnalysisResult(AnalysisResult analysisResult)
 
void postArtifacts(Collection< BlackboardArtifact > artifacts, String moduleName, Long ingestJobId)
 
List< AnalysisResult > getAnalysisResults(long sourceObjId)
 
Collection< BlackboardArtifact > getArtifacts(BlackboardArtifact.Type artifactType)
 
List< BlackboardArtifact > getExactMatchKeywordSearchResults(String keyword, TskData.KeywordSearchQueryType searchType, String kwsListName, Long dataSourceId)
 
List< DataArtifact > getDataArtifacts(int artifactTypeID)
 
List< AnalysisResult > getAnalysisResults(long dataSourceObjId, Integer artifactTypeID)
 
AnalysisResultAdded newAnalysisResult(BlackboardArtifact.Type artifactType, long objId, Long dataSourceObjId, Score score, String conclusion, String configuration, String justification, Collection< BlackboardAttribute > attributesList, CaseDbTransaction transaction)
 
List< AnalysisResult > getAnalysisResultsWhere(String whereClause)
 
List< BlackboardArtifact > getArtifacts(int artifactTypeID, long dataSourceObjId)
 
synchronized BlackboardAttribute.Type getOrAddAttributeType(String typeName, BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType, String displayName)
 
Score deleteAnalysisResult(long artifactObjId, CaseDbTransaction transaction)
 
TimelineManager getTimelineManager()
 
void releaseSingleUserCaseReadLock()
 
static final Type TSK_KEYWORD
 
boolean artifactExists(Content content, BlackboardArtifact.Type artifactType, Collection< BlackboardAttribute > attributes)
 
static final Type TSK_KEYWORD_REGEXP
 
void updateFileAttributes(long fileObjId, List< Attribute > attributes)
 
BlackboardArtifact.Type getArtifactType(String artTypeName)
 
List< AnalysisResult > getAnalysisResults(long sourceObjId, int artifactTypeId)
 
void acquireSingleUserCaseWriteLock()
 
OsAccountInstance newOsAccountInstance(OsAccount osAccount, DataSource dataSource, OsAccountInstance.OsAccountInstanceType instanceType)
 
void postArtifact(BlackboardArtifact artifact, String moduleName, Long ingestJobId)
 
void releaseSingleUserCaseWriteLock()
 
List< BlackboardArtifact > getArtifacts(BlackboardArtifact.Type artifactType, BlackboardAttribute.Type attributeType, String value, Long dataSourceObjId, boolean showRejected)
 
static TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE fromType(long typeId)
 
DataArtifact newDataArtifact(BlackboardArtifact.Type artifactType, long sourceObjId, Long dataSourceObjId, Collection< BlackboardAttribute > attributes, Long osAccountObjId, final CaseDbTransaction transaction)
 
DataArtifact newDataArtifact(BlackboardArtifact.Type artifactType, long sourceObjId, Long dataSourceObjId, Collection< BlackboardAttribute > attributes, Long osAccountObjId, OsAccountInstance.OsAccountInstanceType osAccountInstanceType, final CaseDbTransaction transaction)
 
List< AnalysisResult > getAnalysisResultsByType(int artifactTypeId, long dataSourceObjId)
 
Collection< BlackboardArtifact.Type > getArtifactTypes()
 
List< DataArtifact > getDataArtifactsWhere(String whereClause)
 
AnalysisResultAdded newAnalysisResult(BlackboardArtifact.Type artifactType, long objId, Long dataSourceObjId, Score score, String conclusion, String configuration, String justification, Collection< BlackboardAttribute > attributesList)
 
BlackboardArtifact.Type getOrAddArtifactType(String typeName, String displayName)
 
boolean hasDataArtifacts(long sourceObjId)
 
List< BlackboardArtifact > getKeywordSearchResults(String keyword, String regex, TskData.KeywordSearchQueryType searchType, String kwsListName, Long dataSourceId)
 
static final Type TSK_SET_NAME
 
OsAccountManager getOsAccountManager()
 
void acquireSingleUserCaseReadLock()
 
long getArtifactsCount(int artifactTypeID, long dataSourceObjId)
 
BlackboardAttribute.Type getAttributeType(String attrTypeName)
 
Optional< Long > getIngestJobId()
 
List< BlackboardArtifact.Type > getArtifactTypesInUse(long dataSourceObjId)
 
boolean artifactExists(Content content, BlackboardArtifact.ARTIFACT_TYPE artifactType, Collection< BlackboardAttribute > attributes)
 
static ReviewStatus withID(int id)
 
BlackboardArtifact.Type getArtifactType(int artTypeId)
 
long getArtifactsCount(int artifactTypeID)
 
List< AnalysisResult > getAnalysisResultsByType(int artifactTypeId)
 
ScoringManager getScoringManager()