diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java index 4b477884d6..121bb3ee71 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java @@ -18,6 +18,8 @@ */ package org.sleuthkit.autopsy.centralrepository.datamodel; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -137,54 +139,56 @@ public class CorrelationAttributeUtil { */ public static List makeCorrAttrsForSearch(AnalysisResult analysisResult) { List correlationAttrs = new ArrayList<>(); - try { - int artifactTypeID = analysisResult.getArtifactTypeID(); - if (artifactTypeID == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) { - BlackboardAttribute assocArtifactAttr = analysisResult.getAttribute(BlackboardAttribute.Type.TSK_ASSOCIATED_ARTIFACT); - if (assocArtifactAttr != null) { - BlackboardArtifact sourceArtifact = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboardArtifact(assocArtifactAttr.getValueLong()); - if (sourceArtifact instanceof DataArtifact) { - correlationAttrs.addAll((CorrelationAttributeUtil.makeCorrAttrsForSearch((DataArtifact) sourceArtifact))); - } else if (sourceArtifact instanceof AnalysisResult) { - correlationAttrs.addAll((CorrelationAttributeUtil.makeCorrAttrsForSearch((AnalysisResult) sourceArtifact))); - } else { - String sourceName = sourceArtifact != null ? "SourceArtifact display name: " + sourceArtifact.getDisplayName() : "SourceArtifact was null"; - logger.log(Level.WARNING, "Source artifact found through TSK_ASSOCIATED_ARTIFACT attribute was not a DataArtifact or " - + "an Analysis Result. AssociateArtifactAttr Value: {0} {1}", - new Object[]{assocArtifactAttr.getValueString(), sourceName}); - } + if (CentralRepository.isEnabled()) { + try { + int artifactTypeID = analysisResult.getArtifactTypeID(); + if (artifactTypeID == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) { + BlackboardAttribute assocArtifactAttr = analysisResult.getAttribute(BlackboardAttribute.Type.TSK_ASSOCIATED_ARTIFACT); + if (assocArtifactAttr != null) { + BlackboardArtifact sourceArtifact = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboardArtifact(assocArtifactAttr.getValueLong()); + if (sourceArtifact instanceof DataArtifact) { + correlationAttrs.addAll((CorrelationAttributeUtil.makeCorrAttrsForSearch((DataArtifact) sourceArtifact))); + } else if (sourceArtifact instanceof AnalysisResult) { + correlationAttrs.addAll((CorrelationAttributeUtil.makeCorrAttrsForSearch((AnalysisResult) sourceArtifact))); + } else { + String sourceName = sourceArtifact != null ? "SourceArtifact display name: " + sourceArtifact.getDisplayName() : "SourceArtifact was null"; + logger.log(Level.WARNING, "Source artifact found through TSK_ASSOCIATED_ARTIFACT attribute was not a DataArtifact or " + + "an Analysis Result. AssociateArtifactAttr Value: {0} {1}", + new Object[]{assocArtifactAttr.getValueString(), sourceName}); + } - } - } else { - if (artifactTypeID == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) { - BlackboardAttribute setNameAttr = analysisResult.getAttribute(BlackboardAttribute.Type.TSK_SET_NAME); - if (setNameAttr != null && CorrelationAttributeUtil.getEmailAddressAttrDisplayName().equals(setNameAttr.getValueString())) { - correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(analysisResult, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD, CorrelationAttributeInstance.EMAIL_TYPE_ID, analysisResult.getAttributes())); } - } - Content parent = analysisResult.getParent(); - if (parent instanceof AbstractFile) { - correlationAttrs.addAll(CorrelationAttributeUtil.makeCorrAttrsForSearch((AbstractFile) parent)); - } else if (parent instanceof AnalysisResult) { - correlationAttrs.addAll(CorrelationAttributeUtil.makeCorrAttrsForSearch((AnalysisResult) parent)); - } else if (parent instanceof DataArtifact) { - correlationAttrs.addAll(CorrelationAttributeUtil.makeCorrAttrsForSearch((DataArtifact) parent)); - } else if (parent instanceof OsAccount) { - for (OsAccountInstance osAccountInst : ((OsAccount) parent).getOsAccountInstances()) { - if (osAccountInst.getDataSource().equals(analysisResult.getDataSource())) { - correlationAttrs.addAll(CorrelationAttributeUtil.makeCorrAttrsForSearch(osAccountInst)); - break; + } else { + if (artifactTypeID == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) { + BlackboardAttribute setNameAttr = analysisResult.getAttribute(BlackboardAttribute.Type.TSK_SET_NAME); + if (setNameAttr != null && CorrelationAttributeUtil.getEmailAddressAttrDisplayName().equals(setNameAttr.getValueString())) { + correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(analysisResult, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD, CorrelationAttributeInstance.EMAIL_TYPE_ID, analysisResult.getAttributes())); + } + } + Content parent = analysisResult.getParent(); + if (parent instanceof AbstractFile) { + correlationAttrs.addAll(CorrelationAttributeUtil.makeCorrAttrsForSearch((AbstractFile) parent)); + } else if (parent instanceof AnalysisResult) { + correlationAttrs.addAll(CorrelationAttributeUtil.makeCorrAttrsForSearch((AnalysisResult) parent)); + } else if (parent instanceof DataArtifact) { + correlationAttrs.addAll(CorrelationAttributeUtil.makeCorrAttrsForSearch((DataArtifact) parent)); + } else if (parent instanceof OsAccount) { + for (OsAccountInstance osAccountInst : ((OsAccount) parent).getOsAccountInstances()) { + if (osAccountInst.getDataSource().equals(analysisResult.getDataSource())) { + correlationAttrs.addAll(CorrelationAttributeUtil.makeCorrAttrsForSearch(osAccountInst)); + break; + } } } } - } - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Failed to get information regarding correlation attributes from AnalysisResult", ex); - } catch (NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Attempted to retrieve correlation attributes for search with no currently open case.", ex); - } catch (CentralRepoException ex) { - logger.log(Level.SEVERE, "Failed to get correlation type from central repository.", ex); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Failed to get information regarding correlation attributes from AnalysisResult", ex); + } catch (NoCurrentCaseException ex) { + logger.log(Level.SEVERE, "Attempted to retrieve correlation attributes for search with no currently open case.", ex); + } catch (CentralRepoException ex) { + logger.log(Level.SEVERE, "Failed to get correlation type from central repository.", ex); + } } return correlationAttrs; } @@ -209,94 +213,95 @@ public class CorrelationAttributeUtil { */ public static List makeCorrAttrsForSearch(DataArtifact artifact) { List correlationAttrs = new ArrayList<>(); - try { + if (CentralRepository.isEnabled()) { + try { + List attributes = artifact.getAttributes(); - List attributes = artifact.getAttributes(); + int artifactTypeID = artifact.getArtifactTypeID(); + if (DOMAIN_ARTIFACT_TYPE_IDS.contains(artifactTypeID)) { + BlackboardAttribute domainAttr = getAttribute(attributes, new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DOMAIN)); + if ((domainAttr != null) + && !domainsToSkip.contains(domainAttr.getValueString())) { + correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN, CorrelationAttributeInstance.DOMAIN_TYPE_ID, attributes)); + } + } else if (artifactTypeID == ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID()) { + // prefetch all the information as we will be calling makeCorrAttrFromArtifactAttr() multiple times + Content sourceContent = Case.getCurrentCaseThrows().getSleuthkitCase().getContentById(artifact.getObjectID()); + Content dataSource = sourceContent.getDataSource(); + correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_ID, CorrelationAttributeInstance.USBID_TYPE_ID, + attributes, sourceContent, dataSource)); + correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MAC_ADDRESS, CorrelationAttributeInstance.MAC_TYPE_ID, + attributes, sourceContent, dataSource)); + } else if (artifactTypeID == ARTIFACT_TYPE.TSK_WIFI_NETWORK.getTypeID()) { + correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SSID, CorrelationAttributeInstance.SSID_TYPE_ID, attributes)); + } else if (artifactTypeID == ARTIFACT_TYPE.TSK_WIFI_NETWORK_ADAPTER.getTypeID() + || artifactTypeID == ARTIFACT_TYPE.TSK_BLUETOOTH_PAIRING.getTypeID() + || artifactTypeID == ARTIFACT_TYPE.TSK_BLUETOOTH_ADAPTER.getTypeID()) { + correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MAC_ADDRESS, CorrelationAttributeInstance.MAC_TYPE_ID, attributes)); + } else if (artifactTypeID == ARTIFACT_TYPE.TSK_DEVICE_INFO.getTypeID()) { + // prefetch all the information as we will be calling makeCorrAttrFromArtifactAttr() multiple times + Content sourceContent = Case.getCurrentCaseThrows().getSleuthkitCase().getContentById(artifact.getObjectID()); + Content dataSource = sourceContent.getDataSource(); + correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMEI, CorrelationAttributeInstance.IMEI_TYPE_ID, + attributes, sourceContent, dataSource)); + correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMSI, CorrelationAttributeInstance.IMSI_TYPE_ID, + attributes, sourceContent, dataSource)); + correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ICCID, CorrelationAttributeInstance.ICCID_TYPE_ID, + attributes, sourceContent, dataSource)); - int artifactTypeID = artifact.getArtifactTypeID(); - if (DOMAIN_ARTIFACT_TYPE_IDS.contains(artifactTypeID)) { - BlackboardAttribute domainAttr = getAttribute(attributes, new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DOMAIN)); - if ((domainAttr != null) - && !domainsToSkip.contains(domainAttr.getValueString())) { - correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN, CorrelationAttributeInstance.DOMAIN_TYPE_ID, attributes)); + } else if (artifactTypeID == ARTIFACT_TYPE.TSK_SIM_ATTACHED.getTypeID()) { + // prefetch all the information as we will be calling makeCorrAttrFromArtifactAttr() multiple times + Content sourceContent = Case.getCurrentCaseThrows().getSleuthkitCase().getContentById(artifact.getObjectID()); + Content dataSource = sourceContent.getDataSource(); + correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMSI, CorrelationAttributeInstance.IMSI_TYPE_ID, + attributes, sourceContent, dataSource)); + correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ICCID, CorrelationAttributeInstance.ICCID_TYPE_ID, + attributes, sourceContent, dataSource)); + + } else if (artifactTypeID == ARTIFACT_TYPE.TSK_WEB_FORM_ADDRESS.getTypeID()) { + // prefetch all the information as we will be calling makeCorrAttrFromArtifactAttr() multiple times + Content sourceContent = Case.getCurrentCaseThrows().getSleuthkitCase().getContentById(artifact.getObjectID()); + Content dataSource = sourceContent.getDataSource(); + correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, CorrelationAttributeInstance.PHONE_TYPE_ID, + attributes, sourceContent, dataSource)); + correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, CorrelationAttributeInstance.EMAIL_TYPE_ID, + attributes, sourceContent, dataSource)); + + } else if (artifactTypeID == ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()) { + makeCorrAttrFromAcctArtifact(correlationAttrs, artifact); + + } else if (artifactTypeID == ARTIFACT_TYPE.TSK_INSTALLED_PROG.getTypeID()) { + BlackboardAttribute setNameAttr = getAttribute(attributes, new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH)); + String pathAttrString = null; + if (setNameAttr != null) { + pathAttrString = setNameAttr.getValueString(); + } + if (pathAttrString != null && !pathAttrString.isEmpty()) { + correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH, CorrelationAttributeInstance.INSTALLED_PROGS_TYPE_ID, attributes)); + } else { + correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, CorrelationAttributeInstance.INSTALLED_PROGS_TYPE_ID, attributes)); + } + } else if (artifactTypeID == ARTIFACT_TYPE.TSK_CONTACT.getTypeID() + || artifactTypeID == ARTIFACT_TYPE.TSK_CALLLOG.getTypeID() + || artifactTypeID == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()) { + correlationAttrs.addAll(makeCorrAttrsFromCommunicationArtifact(artifact, attributes)); } - } else if (artifactTypeID == ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID()) { - // prefetch all the information as we will be calling makeCorrAttrFromArtifactAttr() multiple times - Content sourceContent = Case.getCurrentCaseThrows().getSleuthkitCase().getContentById(artifact.getObjectID()); - Content dataSource = sourceContent.getDataSource(); - correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_ID, CorrelationAttributeInstance.USBID_TYPE_ID, - attributes, sourceContent, dataSource)); - correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MAC_ADDRESS, CorrelationAttributeInstance.MAC_TYPE_ID, - attributes, sourceContent, dataSource)); - } else if (artifactTypeID == ARTIFACT_TYPE.TSK_WIFI_NETWORK.getTypeID()) { - correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SSID, CorrelationAttributeInstance.SSID_TYPE_ID, attributes)); - } else if (artifactTypeID == ARTIFACT_TYPE.TSK_WIFI_NETWORK_ADAPTER.getTypeID() - || artifactTypeID == ARTIFACT_TYPE.TSK_BLUETOOTH_PAIRING.getTypeID() - || artifactTypeID == ARTIFACT_TYPE.TSK_BLUETOOTH_ADAPTER.getTypeID()) { - correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MAC_ADDRESS, CorrelationAttributeInstance.MAC_TYPE_ID, attributes)); - } else if (artifactTypeID == ARTIFACT_TYPE.TSK_DEVICE_INFO.getTypeID()) { - // prefetch all the information as we will be calling makeCorrAttrFromArtifactAttr() multiple times - Content sourceContent = Case.getCurrentCaseThrows().getSleuthkitCase().getContentById(artifact.getObjectID()); - Content dataSource = sourceContent.getDataSource(); - correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMEI, CorrelationAttributeInstance.IMEI_TYPE_ID, - attributes, sourceContent, dataSource)); - correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMSI, CorrelationAttributeInstance.IMSI_TYPE_ID, - attributes, sourceContent, dataSource)); - correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ICCID, CorrelationAttributeInstance.ICCID_TYPE_ID, - attributes, sourceContent, dataSource)); - - } else if (artifactTypeID == ARTIFACT_TYPE.TSK_SIM_ATTACHED.getTypeID()) { - // prefetch all the information as we will be calling makeCorrAttrFromArtifactAttr() multiple times - Content sourceContent = Case.getCurrentCaseThrows().getSleuthkitCase().getContentById(artifact.getObjectID()); - Content dataSource = sourceContent.getDataSource(); - correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMSI, CorrelationAttributeInstance.IMSI_TYPE_ID, - attributes, sourceContent, dataSource)); - correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ICCID, CorrelationAttributeInstance.ICCID_TYPE_ID, - attributes, sourceContent, dataSource)); - - } else if (artifactTypeID == ARTIFACT_TYPE.TSK_WEB_FORM_ADDRESS.getTypeID()) { - // prefetch all the information as we will be calling makeCorrAttrFromArtifactAttr() multiple times - Content sourceContent = Case.getCurrentCaseThrows().getSleuthkitCase().getContentById(artifact.getObjectID()); - Content dataSource = sourceContent.getDataSource(); - correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, CorrelationAttributeInstance.PHONE_TYPE_ID, - attributes, sourceContent, dataSource)); - correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, CorrelationAttributeInstance.EMAIL_TYPE_ID, - attributes, sourceContent, dataSource)); - - } else if (artifactTypeID == ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()) { - makeCorrAttrFromAcctArtifact(correlationAttrs, artifact); - - } else if (artifactTypeID == ARTIFACT_TYPE.TSK_INSTALLED_PROG.getTypeID()) { - BlackboardAttribute setNameAttr = getAttribute(attributes, new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH)); - String pathAttrString = null; - if (setNameAttr != null) { - pathAttrString = setNameAttr.getValueString(); - } - if (pathAttrString != null && !pathAttrString.isEmpty()) { - correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH, CorrelationAttributeInstance.INSTALLED_PROGS_TYPE_ID, attributes)); - } else { - correlationAttrs.addAll(makeCorrAttrFromArtifactAttr(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, CorrelationAttributeInstance.INSTALLED_PROGS_TYPE_ID, attributes)); - } - } else if (artifactTypeID == ARTIFACT_TYPE.TSK_CONTACT.getTypeID() - || artifactTypeID == ARTIFACT_TYPE.TSK_CALLLOG.getTypeID() - || artifactTypeID == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()) { - correlationAttrs.addAll(makeCorrAttrsFromCommunicationArtifact(artifact, attributes)); + } catch (CorrelationAttributeNormalizationException ex) { + logger.log(Level.WARNING, String.format("Error normalizing correlation attribute (%s)", artifact), ex); // NON-NLS + return correlationAttrs; + } catch (InvalidAccountIDException ex) { + logger.log(Level.WARNING, String.format("Invalid account identifier (artifactID: %d)", artifact.getId())); // NON-NLS + return correlationAttrs; + } catch (CentralRepoException ex) { + logger.log(Level.SEVERE, String.format("Error querying central repository (%s)", artifact), ex); // NON-NLS + return correlationAttrs; + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Error getting querying case database (%s)", artifact), ex); // NON-NLS + return correlationAttrs; + } catch (NoCurrentCaseException ex) { + logger.log(Level.SEVERE, "Error getting current case", ex); // NON-NLS + return correlationAttrs; } - } catch (CorrelationAttributeNormalizationException ex) { - logger.log(Level.WARNING, String.format("Error normalizing correlation attribute (%s)", artifact), ex); // NON-NLS - return correlationAttrs; - } catch (InvalidAccountIDException ex) { - logger.log(Level.WARNING, String.format("Invalid account identifier (artifactID: %d)", artifact.getId())); // NON-NLS - return correlationAttrs; - } catch (CentralRepoException ex) { - logger.log(Level.SEVERE, String.format("Error querying central repository (%s)", artifact), ex); // NON-NLS - return correlationAttrs; - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, String.format("Error getting querying case database (%s)", artifact), ex); // NON-NLS - return correlationAttrs; - } catch (NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Error getting current case", ex); // NON-NLS - return correlationAttrs; } return correlationAttrs; } @@ -543,7 +548,7 @@ public class CorrelationAttributeUtil { CorrelationCase correlationCase = CentralRepository.getInstance().getCase(Case.getCurrentCaseThrows()); if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INSTALLED_PROG.getTypeID() - || ! (srcContent instanceof AbstractFile)) { + || !(srcContent instanceof AbstractFile)) { return new CorrelationAttributeInstance( correlationType, value, @@ -685,7 +690,7 @@ public class CorrelationAttributeUtil { */ public static List makeCorrAttrsForSearch(AbstractFile file) { List fileTypeList = new ArrayList<>(); // will be an empty or single element list as was decided in 7852 - if (!isSupportedAbstractFileType(file)) { + if (!isSupportedAbstractFileType(file) || !CentralRepository.isEnabled()) { return fileTypeList; } @@ -754,46 +759,118 @@ public class CorrelationAttributeUtil { public static List makeCorrAttrsForSearch(OsAccountInstance osAccountInst) { List correlationAttrs = new ArrayList<>(); - OsAccount account = null; - DataSource dataSource = null; - if (osAccountInst != null) { - try { - account = osAccountInst.getOsAccount(); - dataSource = osAccountInst.getDataSource(); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error getting information from OsAccountInstance.", ex); - } - } - if (account != null && dataSource != null) { - Optional accountAddr = account.getAddr(); - // Check address if it is null or one of the ones below we want to ignore it since they will always be one a windows system - // and they are not unique - if (accountAddr.isPresent() && !accountAddr.get().equals("S-1-5-18") && !accountAddr.get().equals("S-1-5-19") && !accountAddr.get().equals("S-1-5-20")) { + if (CentralRepository.isEnabled()) { + OsAccount account = null; + DataSource dataSource = null; + if (osAccountInst != null) { try { + account = osAccountInst.getOsAccount(); + dataSource = osAccountInst.getDataSource(); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error getting information from OsAccountInstance.", ex); + } + } + if (account != null && dataSource != null) { + Optional accountAddr = account.getAddr(); + // Check address if it is null or one of the ones below we want to ignore it since they will always be one a windows system + // and they are not unique + if (accountAddr.isPresent() && !accountAddr.get().equals("S-1-5-18") && !accountAddr.get().equals("S-1-5-19") && !accountAddr.get().equals("S-1-5-20")) { + try { - CorrelationCase correlationCase = CentralRepository.getInstance().getCase(Case.getCurrentCaseThrows()); - CorrelationAttributeInstance correlationAttributeInstance = new CorrelationAttributeInstance( - CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.OSACCOUNT_TYPE_ID), - accountAddr.get(), - correlationCase, - CorrelationDataSource.fromTSKDataSource(correlationCase, dataSource), - "", - "", - TskData.FileKnown.KNOWN, - account.getId()); - correlationAttrs.add(correlationAttributeInstance); - } catch (CentralRepoException ex) { - logger.log(Level.SEVERE, String.format("Cannot get central repository for OsAccount: %s.", accountAddr.get()), ex); //NON-NLS - } catch (NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS - } catch (CorrelationAttributeNormalizationException ex) { - logger.log(Level.SEVERE, "Exception with Correlation Attribute Normalization.", ex); //NON-NLS + CorrelationCase correlationCase = CentralRepository.getInstance().getCase(Case.getCurrentCaseThrows()); + CorrelationAttributeInstance correlationAttributeInstance = new CorrelationAttributeInstance( + CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.OSACCOUNT_TYPE_ID), + accountAddr.get(), + correlationCase, + CorrelationDataSource.fromTSKDataSource(correlationCase, dataSource), + "", + "", + TskData.FileKnown.KNOWN, + account.getId()); + correlationAttrs.add(correlationAttributeInstance); + } catch (CentralRepoException ex) { + logger.log(Level.SEVERE, String.format("Cannot get central repository for OsAccount: %s.", accountAddr.get()), ex); //NON-NLS + } catch (NoCurrentCaseException ex) { + logger.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS + } catch (CorrelationAttributeNormalizationException ex) { + logger.log(Level.SEVERE, "Exception with Correlation Attribute Normalization.", ex); //NON-NLS + } } } } return correlationAttrs; } + /** + * Check if any of the specified attribute values in the CR have a + * non-empty, non null comment. + * + * @param attributes The list of attributes to check the type value matches + * of for the presence of a comment. + * + * @return True if any the type value matches in the CR have a comment in + * their respective comment column, false if there are no comments + * or the CR is disabled. + * + * @throws CentralRepoException Thrown when there is an issue either getting + * the CentralRepository instance or executing + * a query. + */ + public static boolean commentExistsOnAttributes(List attributes) throws CentralRepoException { + boolean commentExists = false; + if (CentralRepository.isEnabled() && !attributes.isEmpty()) { + CentralRepository crInstance = CentralRepository.getInstance(); + //Query to check for the presence of a comment on any matching value in the specified table. + String sqlSelect = "SELECT EXISTS " + + "(SELECT 1 " + + "FROM "; + String sqlWhere = " WHERE value=? " + + "AND comment<>''" + + "LIMIT 1)"; + List params; + CommentExistsCallback commentCallback = new CommentExistsCallback(); + for (CorrelationAttributeInstance instance : attributes) { + params = new ArrayList<>(); + params.add(instance.getCorrelationValue()); + String sql = sqlSelect + CentralRepoDbUtil.correlationTypeToInstanceTableName(instance.getCorrelationType()) + sqlWhere; + crInstance.executeQuery(sql, params, commentCallback); + if (commentCallback.doesCommentExist()) { + //we are checking a binary condition so as soon as any query returns true we can stop + commentExists = true; + break; + } + } + } + return commentExists; + } + + /** + * Private implementation of the CentralRepositoryDbQueryCallback to parse + * the results of the query which checks if a type value pair has a comment. + */ + private static class CommentExistsCallback implements CentralRepositoryDbQueryCallback { + + private boolean commentExists = false; + + @Override + public void process(ResultSet rs) throws CentralRepoException, SQLException { + //there should only be 1 result here with 1 column + if (rs.next()) { + commentExists = rs.getBoolean(1); + } + } + + /** + * Identifies if a comment existed. + * + * @return True if a comment existed, false otherwise. + */ + boolean doesCommentExist() { + return commentExists; + } + + } + /** * Prevent instantiation of this utility class. */ diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index 4b9ab561b1..2f47d2bc80 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -709,14 +709,22 @@ public final class CaseEventListener implements PropertyChangeListener { // Look up and create artifacts for previously seen accounts if requested if (IngestEventsListener.isFlagSeenDevices()) { + CorrelationAttributeInstance.Type osAcctType = CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.OSACCOUNT_TYPE_ID); - List previousOccurences = dbManager.getArtifactInstancesByTypeValue(osAcctType, correlationAttributeInstances.get(0).getCorrelationValue()); + CorrelationAttributeInstance instanceWithTypeValue = null; + for (CorrelationAttributeInstance instance : correlationAttributeInstances){ + if (instance.getCorrelationType().getId() == CorrelationAttributeInstance.OSACCOUNT_TYPE_ID) { + instanceWithTypeValue = instance; + } + } + List previousOccurences = dbManager.getArtifactInstancesByTypeValue(instanceWithTypeValue.getCorrelationType(), instanceWithTypeValue.getCorrelationValue()); for (CorrelationAttributeInstance instance : previousOccurences) { - if (!instance.getCorrelationCase().getCaseUUID().equals(correlationAttributeInstances.get(0).getCorrelationCase().getCaseUUID())) { + //we can get the first instance here since the case for all attributes will be the same + if (!instance.getCorrelationCase().getCaseUUID().equals(instanceWithTypeValue.getCorrelationCase().getCaseUUID())) { SleuthkitCase tskCase = osAccount.getSleuthkitCase(); Blackboard blackboard = tskCase.getBlackboard(); - List caseDisplayNames = dbManager.getListCasesHavingArtifactInstances(osAcctType, correlationAttributeInstances.get(0).getCorrelationValue()); + List caseDisplayNames = dbManager.getListCasesHavingArtifactInstances(osAcctType, instanceWithTypeValue.getCorrelationValue()); // calculate score Score score; @@ -741,7 +749,7 @@ public final class CaseEventListener implements PropertyChangeListener { osAcctType.getDisplayName()), new BlackboardAttribute( TSK_CORRELATION_VALUE, MODULE_NAME, - correlationAttributeInstances.get(0).getCorrelationValue()), + instanceWithTypeValue.getCorrelationValue()), new BlackboardAttribute( TSK_OTHER_CASES, MODULE_NAME, prevCases)); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java index c242128461..634f12b49b 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java @@ -434,9 +434,9 @@ public abstract class AbstractAbstractFileNode extends A description = Bundle.AbstractAbstractFileNode_createSheet_count_hashLookupNotRun_description(); } } catch (CentralRepoException ex) { - logger.log(Level.WARNING, "Error getting count of datasources with correlation attribute", ex); + logger.log(Level.SEVERE, "Error getting count of datasources with correlation attribute", ex); } catch (CorrelationAttributeNormalizationException ex) { - logger.log(Level.WARNING, "Unable to normalize data to get count of datasources with correlation attribute", ex); + logger.log(Level.SEVERE, "Unable to normalize data to get count of datasources with correlation attribute", ex); } return Pair.of(count, description); } @@ -445,9 +445,7 @@ public abstract class AbstractAbstractFileNode extends A "AbstractAbstractFileNode.createSheet.comment.displayName=C"}) @Override protected HasCommentStatus getCommentProperty(List tags, List attributes) { - DataResultViewerTable.HasCommentStatus status = !tags.isEmpty() ? DataResultViewerTable.HasCommentStatus.TAG_NO_COMMENT : DataResultViewerTable.HasCommentStatus.NO_COMMENT; - for (Tag tag : tags) { if (!StringUtils.isBlank(tag.getComment())) { //if the tag is null or empty or contains just white space it will indicate there is not a comment @@ -455,17 +453,20 @@ public abstract class AbstractAbstractFileNode extends A break; } } - if (attributes != null && !attributes.isEmpty()) { - for (CorrelationAttributeInstance attribute : attributes) { - if (attribute != null && !StringUtils.isBlank(attribute.getComment())) { - if (status == DataResultViewerTable.HasCommentStatus.TAG_COMMENT) { - status = DataResultViewerTable.HasCommentStatus.CR_AND_TAG_COMMENTS; - } else { - status = DataResultViewerTable.HasCommentStatus.CR_COMMENT; - } - break; + /* + * Is there a comment in the CR for anything that matches the value and + * type of the specified attributes. + */ + try { + if (CorrelationAttributeUtil.commentExistsOnAttributes(attributes)) { + if (status == DataResultViewerTable.HasCommentStatus.TAG_COMMENT) { + status = DataResultViewerTable.HasCommentStatus.CR_AND_TAG_COMMENTS; + } else { + status = DataResultViewerTable.HasCommentStatus.CR_COMMENT; } } + } catch (CentralRepoException ex) { + logger.log(Level.SEVERE, "Attempted to Query CR for presence of comments in a file node and was unable to perform query, comment column will only reflect caseDB", ex); } return status; } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentNode.java index 80e60e6cc8..b81a495e42 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentNode.java @@ -25,10 +25,10 @@ import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.logging.Level; +import javax.swing.SwingUtilities; import org.apache.commons.lang3.tuple.Pair; import org.openide.nodes.Children; import org.openide.nodes.Sheet; - import org.openide.util.lookup.Lookups; import org.openide.util.Lookup; import org.openide.util.NbBundle; @@ -299,22 +299,27 @@ public abstract class AbstractContentNode extends ContentNode * sheet. */ protected synchronized void updateSheet(NodeProperty... newProps) { - //Refresh ONLY those properties in the sheet currently. Subclasses may have - //only added a subset of our properties or their own props.s - Sheet visibleSheet = this.getSheet(); - Sheet.Set visibleSheetSet = visibleSheet.get(Sheet.PROPERTIES); - Property[] visibleProps = visibleSheetSet.getProperties(); - for (NodeProperty newProp : newProps) { - for (int i = 0; i < visibleProps.length; i++) { - if (visibleProps[i].getName().equals(newProp.getName())) { - visibleProps[i] = newProp; + SwingUtilities.invokeLater(() -> { + /* + * Refresh ONLY those properties in the sheet currently. Subclasses + * may have only added a subset of our properties or their own + * properties. + */ + Sheet visibleSheet = this.getSheet(); + Sheet.Set visibleSheetSet = visibleSheet.get(Sheet.PROPERTIES); + Property[] visibleProps = visibleSheetSet.getProperties(); + for (NodeProperty newProp : newProps) { + for (int i = 0; i < visibleProps.length; i++) { + if (visibleProps[i].getName().equals(newProp.getName())) { + visibleProps[i] = newProp; + } } } - } - visibleSheetSet.put(visibleProps); - visibleSheet.put(visibleSheetSet); - //setSheet() will notify Netbeans to update this node in the UI. - this.setSheet(visibleSheet); + visibleSheetSet.put(visibleProps); + visibleSheet.put(visibleSheetSet); + //setSheet() will notify Netbeans to update this node in the UI. + this.setSheet(visibleSheet); + }); } /** diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index 3357fccd02..ad8c065dc0 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -85,6 +85,7 @@ import org.sleuthkit.datamodel.Tag; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.datamodel.utils.IconsUtil; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeUtil; import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; import static org.sleuthkit.autopsy.datamodel.AbstractContentNode.NO_DESCR; @@ -878,18 +879,18 @@ public class BlackboardArtifactNode extends AbstractContentNode( - Bundle.BlackboardArtifactNode_createSheet_srcFile_name(), - Bundle.BlackboardArtifactNode_createSheet_srcFile_displayName(), - NO_DESCR, - getDisplayName())); + * Add the name of the source content of the artifact represented by + * this node to the sheet. The value of this property is the same as the + * display name of the node and this a "special" property that displays + * the node's icon as well as the display name. + */ + sheetSet.put(new NodeProperty<>( + Bundle.BlackboardArtifactNode_createSheet_srcFile_name(), + Bundle.BlackboardArtifactNode_createSheet_srcFile_displayName(), + NO_DESCR, + getDisplayName())); GetSCOTask scoTask = null; if (artifact instanceof AnalysisResult @@ -1148,7 +1149,7 @@ public class BlackboardArtifactNode extends AbstractContentNode tags, List attributes) { - /* * Has a tag with a comment been applied to the artifact or its source * content? @@ -1202,24 +1202,21 @@ public class BlackboardArtifactNode extends AbstractContentNode { + this.setSheet(createSheet()); + }); } /** @@ -1452,7 +1451,7 @@ public class BlackboardArtifactNode extends AbstractContentNode 1) { @@ -116,7 +151,7 @@ class GetSCOTask implements Runnable { listener.propertyChange(new PropertyChangeEvent( AutopsyEvent.SourceType.LOCAL.toString(), AbstractAbstractFileNode.NodeSpecificEvents.SCO_AVAILABLE.toString(), - null, new SCOData(scoreAndDescription, comment, countAndDescription))); + null, new SCOData(scoreAndDescription, commentStatus, countAndDescription))); } } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/OsAccounts.java b/Core/src/org/sleuthkit/autopsy/datamodel/OsAccounts.java index d88372b6b9..33fb27dc38 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/OsAccounts.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/OsAccounts.java @@ -37,7 +37,6 @@ import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; -import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.openide.util.WeakListeners; @@ -47,6 +46,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException; +import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeUtil; import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable; import org.sleuthkit.autopsy.coreutils.Logger; @@ -287,9 +287,7 @@ public final class OsAccounts implements AutopsyVisitableItem { Bundle.OsAccounts_accountHostNameProperty_desc(), hostsString)); } - - SwingUtilities.invokeLater(() - -> updateSheet(propertiesToUpdate.toArray(new NodeProperty[propertiesToUpdate.size()]))); + updateSheet(propertiesToUpdate.toArray(new NodeProperty[propertiesToUpdate.size()])); } else if (evt.getPropertyName().equals(NodeSpecificEvents.SCO_AVAILABLE.toString()) && !UserPreferences.getHideSCOColumns()) { SCOData scoData = (SCOData) evt.getNewValue(); if (scoData.getScoreAndDescription() != null) { @@ -362,7 +360,9 @@ public final class OsAccounts implements AutopsyVisitableItem { * Refreshes this node's property sheet. */ void updateSheet() { - this.setSheet(createSheet()); + SwingUtilities.invokeLater(() -> { + this.setSheet(createSheet()); + }); } @Override @@ -511,9 +511,8 @@ public final class OsAccounts implements AutopsyVisitableItem { OS_ACCOUNT_DATA_AVAILABLE_EVENT, null, evtData)); } - } catch (TskCoreException ex) { - Exceptions.printStackTrace(ex); + logger.log(Level.WARNING, "Error occurred getting realm information for Os Account Node from case db, for account: " + node.getOsAccount().getName(), ex); } } } @@ -536,9 +535,9 @@ public final class OsAccounts implements AutopsyVisitableItem { description = Bundle.OsAccounts_createSheet_count_hashLookupNotRun_description(); } } catch (CentralRepoException ex) { - logger.log(Level.WARNING, "Error getting count of datasources with correlation attribute", ex); + logger.log(Level.SEVERE, "Error getting count of datasources with correlation attribute", ex); } catch (CorrelationAttributeNormalizationException ex) { - logger.log(Level.WARNING, "Unable to normalize data to get count of datasources with correlation attribute", ex); + logger.log(Level.SEVERE, "Unable to normalize data to get count of datasources with correlation attribute", ex); } return Pair.of(count, description); } @@ -553,7 +552,6 @@ public final class OsAccounts implements AutopsyVisitableItem { */ @Override protected DataResultViewerTable.HasCommentStatus getCommentProperty(List tags, List attributes) { - /* * Has a tag with a comment been applied to the OsAccount or its * source content? @@ -565,24 +563,21 @@ public final class OsAccounts implements AutopsyVisitableItem { break; } } - /* - * Does the given correlation attribute instance have a comment in - * the central repository? + * Is there a comment in the CR for anything that matches the value + * and type of the specified attributes. */ - if (attributes != null && !attributes.isEmpty()) { - for (CorrelationAttributeInstance attribute : attributes) { - if (attribute != null && !StringUtils.isBlank(attribute.getComment())) { - if (status == DataResultViewerTable.HasCommentStatus.TAG_COMMENT) { - status = DataResultViewerTable.HasCommentStatus.CR_AND_TAG_COMMENTS; - } else { - status = DataResultViewerTable.HasCommentStatus.CR_COMMENT; - } - break; + try { + if (CorrelationAttributeUtil.commentExistsOnAttributes(attributes)) { + if (status == DataResultViewerTable.HasCommentStatus.TAG_COMMENT) { + status = DataResultViewerTable.HasCommentStatus.CR_AND_TAG_COMMENTS; + } else { + status = DataResultViewerTable.HasCommentStatus.CR_COMMENT; } } + } catch (CentralRepoException ex) { + logger.log(Level.SEVERE, "Attempted to Query CR for presence of comments in an OS Account node and was unable to perform query, comment column will only reflect caseDB", ex); } - return status; } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java b/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java index 9c84b85bfe..3e3c122e71 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java @@ -48,6 +48,7 @@ import javax.annotation.Nonnull; import javax.annotation.concurrent.Immutable; import javax.swing.AbstractAction; import javax.swing.Action; +import javax.swing.SwingUtilities; import org.apache.commons.lang3.StringUtils; import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; @@ -416,7 +417,7 @@ final public class Accounts implements AutopsyVisitableItem { } } }; - + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); @Subscribe @@ -553,9 +554,9 @@ final public class Accounts implements AutopsyVisitableItem { } } }; - + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); - + @Override protected void addNotify() { IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); @@ -731,9 +732,8 @@ final public class Accounts implements AutopsyVisitableItem { } } }; - - private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); @Subscribe @Override @@ -746,7 +746,7 @@ final public class Accounts implements AutopsyVisitableItem { void handleDataAdded(ModuleDataEvent event) { refresh(true); } - + @Override protected void addNotify() { IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); @@ -889,7 +889,7 @@ final public class Accounts implements AutopsyVisitableItem { } } }; - + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); @Override @@ -1105,7 +1105,7 @@ final public class Accounts implements AutopsyVisitableItem { } } }; - + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); @Override @@ -1117,7 +1117,7 @@ final public class Accounts implements AutopsyVisitableItem { } @Override - protected void finalize() throws Throwable{ + protected void finalize() throws Throwable { super.finalize(); IngestManager.getInstance().removeIngestJobEventListener(weakPcl); IngestManager.getInstance().removeIngestModuleEventListener(weakPcl); @@ -1669,7 +1669,9 @@ final public class Accounts implements AutopsyVisitableItem { } private void updateSheet() { - this.setSheet(createSheet()); + SwingUtilities.invokeLater(() -> { + this.setSheet(createSheet()); + }); } } @@ -1846,7 +1848,9 @@ final public class Accounts implements AutopsyVisitableItem { } private void updateSheet() { - this.setSheet(createSheet()); + SwingUtilities.invokeLater(() -> { + this.setSheet(createSheet()); + }); } }