From 4ad575ef41d3654b9602083983260d072bb386f8 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 27 Jun 2016 16:41:03 -0400 Subject: [PATCH 1/6] Made EmailExtracted class thread safe --- .../autopsy/datamodel/EmailExtracted.java | 87 +++++++++++-------- 1 file changed, 49 insertions(+), 38 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java index fecf47d7cd..6523fa2b99 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java @@ -73,61 +73,72 @@ public class EmailExtracted implements AutopsyVisitableItem { private final class EmailResults extends Observable { private final Map>> accounts = new LinkedHashMap<>(); + // "accounts" object can be accessed by multiple threads and needs to be protected with locks + private final Object accountsLock; EmailResults() { + accountsLock = new Object(); update(); } public Set getAccounts() { - return accounts.keySet(); + synchronized (accountsLock) { + return accounts.keySet(); + } } public Set getFolders(String account) { - return accounts.get(account).keySet(); + synchronized (accountsLock) { + return accounts.get(account).keySet(); + } } public List getArtifactIds(String account, String folder) { - return accounts.get(account).get(folder); + synchronized (accountsLock) { + return accounts.get(account).get(folder); + } } @SuppressWarnings("deprecation") public void update() { - accounts.clear(); - if (skCase == null) { - return; - } - - int artId = BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(); - int pathAttrId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID(); - String query = "SELECT value_text,blackboard_attributes.artifact_id,attribute_type_id " //NON-NLS - + "FROM blackboard_attributes,blackboard_artifacts WHERE " //NON-NLS - + "attribute_type_id=" + pathAttrId //NON-NLS - + " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //NON-NLS - + " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS - - try (CaseDbQuery dbQuery = skCase.executeQuery(query)) { - ResultSet resultSet = dbQuery.getResultSet(); - while (resultSet.next()) { - final String path = resultSet.getString("value_text"); //NON-NLS - final long artifactId = resultSet.getLong("artifact_id"); //NON-NLS - final Map parsedPath = parsePath(path); - final String account = parsedPath.get(MAIL_ACCOUNT); - final String folder = parsedPath.get(MAIL_FOLDER); - - Map> folders = accounts.get(account); - if (folders == null) { - folders = new LinkedHashMap<>(); - accounts.put(account, folders); - } - List messages = folders.get(folder); - if (messages == null) { - messages = new ArrayList<>(); - folders.put(folder, messages); - } - messages.add(artifactId); + synchronized (accountsLock) { + accounts.clear(); + if (skCase == null) { + return; + } + + int artId = BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(); + int pathAttrId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID(); + String query = "SELECT value_text,blackboard_attributes.artifact_id,attribute_type_id " //NON-NLS + + "FROM blackboard_attributes,blackboard_artifacts WHERE " //NON-NLS + + "attribute_type_id=" + pathAttrId //NON-NLS + + " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //NON-NLS + + " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS + + try (CaseDbQuery dbQuery = skCase.executeQuery(query)) { + ResultSet resultSet = dbQuery.getResultSet(); + while (resultSet.next()) { + final String path = resultSet.getString("value_text"); //NON-NLS + final long artifactId = resultSet.getLong("artifact_id"); //NON-NLS + final Map parsedPath = parsePath(path); + final String account = parsedPath.get(MAIL_ACCOUNT); + final String folder = parsedPath.get(MAIL_FOLDER); + + Map> folders = accounts.get(account); + if (folders == null) { + folders = new LinkedHashMap<>(); + accounts.put(account, folders); + } + List messages = folders.get(folder); + if (messages == null) { + messages = new ArrayList<>(); + folders.put(folder, messages); + } + messages.add(artifactId); + } + } catch (TskCoreException | SQLException ex) { + logger.log(Level.WARNING, "Cannot initialize email extraction: ", ex); //NON-NLS } - } catch (TskCoreException | SQLException ex) { - logger.log(Level.WARNING, "Cannot initialize email extraction: ", ex); //NON-NLS } } From f641128cb07f7f28225d9b6bb3152de45149bac7 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 27 Jun 2016 17:16:54 -0400 Subject: [PATCH 2/6] Made EmailExtracted class thread safe --- .../sleuthkit/autopsy/datamodel/EmailExtracted.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java index 6523fa2b99..8fe73099e2 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java @@ -72,36 +72,34 @@ public class EmailExtracted implements AutopsyVisitableItem { private final class EmailResults extends Observable { + // NOTE: "accounts" object can be accessed by multiple threads and needs to be synchronized private final Map>> accounts = new LinkedHashMap<>(); - // "accounts" object can be accessed by multiple threads and needs to be protected with locks - private final Object accountsLock; EmailResults() { - accountsLock = new Object(); update(); } public Set getAccounts() { - synchronized (accountsLock) { + synchronized (accounts) { return accounts.keySet(); } } public Set getFolders(String account) { - synchronized (accountsLock) { + synchronized (accounts) { return accounts.get(account).keySet(); } } public List getArtifactIds(String account, String folder) { - synchronized (accountsLock) { + synchronized (accounts) { return accounts.get(account).get(folder); } } @SuppressWarnings("deprecation") public void update() { - synchronized (accountsLock) { + synchronized (accounts) { accounts.clear(); if (skCase == null) { return; From d0f70d4642c036b0fcb57d01d0a340878161801e Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 27 Jun 2016 17:19:57 -0400 Subject: [PATCH 3/6] Made HashsetHits class thread safe --- .../autopsy/datamodel/HashsetHits.java | 67 ++++++++++--------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java index 6ecaec6258..cad0c4c03f 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java @@ -78,7 +78,7 @@ public class HashsetHits implements AutopsyVisitableItem { private class HashsetResults extends Observable { // maps hashset name to list of artifacts for that set - + // NOTE: "hashSetHitsMap" object can be accessed by multiple threads and needs to be synchronized private final Map> hashSetHitsMap = new LinkedHashMap<>(); HashsetResults() { @@ -86,47 +86,54 @@ public class HashsetHits implements AutopsyVisitableItem { } List getSetNames() { - List names = new ArrayList<>(hashSetHitsMap.keySet()); + List names; + synchronized (hashSetHitsMap) { + names = new ArrayList<>(hashSetHitsMap.keySet()); + } Collections.sort(names); return names; } Set getArtifactIds(String hashSetName) { - return hashSetHitsMap.get(hashSetName); + synchronized (hashSetHitsMap) { + return hashSetHitsMap.get(hashSetName); + } } @SuppressWarnings("deprecation") final void update() { - hashSetHitsMap.clear(); + synchronized (hashSetHitsMap) { + hashSetHitsMap.clear(); - if (skCase == null) { - return; - } - - int setNameId = ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(); - int artId = ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(); - String query = "SELECT value_text,blackboard_attributes.artifact_id,attribute_type_id " //NON-NLS - + "FROM blackboard_attributes,blackboard_artifacts WHERE " //NON-NLS - + "attribute_type_id=" + setNameId //NON-NLS - + " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //NON-NLS - + " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS - - try (CaseDbQuery dbQuery = skCase.executeQuery(query)) { - ResultSet resultSet = dbQuery.getResultSet(); - while (resultSet.next()) { - String setName = resultSet.getString("value_text"); //NON-NLS - long artifactId = resultSet.getLong("artifact_id"); //NON-NLS - if (!hashSetHitsMap.containsKey(setName)) { - hashSetHitsMap.put(setName, new HashSet()); - } - hashSetHitsMap.get(setName).add(artifactId); + if (skCase == null) { + return; } - } catch (TskCoreException | SQLException ex) { - logger.log(Level.WARNING, "SQL Exception occurred: ", ex); //NON-NLS - } - setChanged(); - notifyObservers(); + int setNameId = ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(); + int artId = ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(); + String query = "SELECT value_text,blackboard_attributes.artifact_id,attribute_type_id " //NON-NLS + + "FROM blackboard_attributes,blackboard_artifacts WHERE " //NON-NLS + + "attribute_type_id=" + setNameId //NON-NLS + + " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //NON-NLS + + " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS + + try (CaseDbQuery dbQuery = skCase.executeQuery(query)) { + ResultSet resultSet = dbQuery.getResultSet(); + while (resultSet.next()) { + String setName = resultSet.getString("value_text"); //NON-NLS + long artifactId = resultSet.getLong("artifact_id"); //NON-NLS + if (!hashSetHitsMap.containsKey(setName)) { + hashSetHitsMap.put(setName, new HashSet()); + } + hashSetHitsMap.get(setName).add(artifactId); + } + } catch (TskCoreException | SQLException ex) { + logger.log(Level.WARNING, "SQL Exception occurred: ", ex); //NON-NLS + } + + setChanged(); + notifyObservers(); + } } } From ced9398da38bd5da93db31b6952068da817f5f9e Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Tue, 28 Jun 2016 10:37:46 -0400 Subject: [PATCH 4/6] Updated comments --- Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java | 2 +- Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java index 8fe73099e2..841fe6aab8 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java @@ -72,7 +72,7 @@ public class EmailExtracted implements AutopsyVisitableItem { private final class EmailResults extends Observable { - // NOTE: "accounts" object can be accessed by multiple threads and needs to be synchronized + // NOTE: the map can be accessed by multiple worker threads and needs to be synchronized private final Map>> accounts = new LinkedHashMap<>(); EmailResults() { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java index cad0c4c03f..41f3efc122 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java @@ -78,7 +78,7 @@ public class HashsetHits implements AutopsyVisitableItem { private class HashsetResults extends Observable { // maps hashset name to list of artifacts for that set - // NOTE: "hashSetHitsMap" object can be accessed by multiple threads and needs to be synchronized + // NOTE: the map can be accessed by multiple worker threads and needs to be synchronized private final Map> hashSetHitsMap = new LinkedHashMap<>(); HashsetResults() { From d2cb90f8d81400df58e794aee90c0e0fb19d5bc5 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Tue, 28 Jun 2016 11:07:33 -0400 Subject: [PATCH 5/6] Added thread safety to InterestingResults class --- .../autopsy/datamodel/EmailExtracted.java | 30 ++++++++-------- .../autopsy/datamodel/HashsetHits.java | 36 ++++++++++--------- .../autopsy/datamodel/InterestingHits.java | 30 ++++++++++------ 3 files changed, 55 insertions(+), 41 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java index 841fe6aab8..35af75738b 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java @@ -101,20 +101,22 @@ public class EmailExtracted implements AutopsyVisitableItem { public void update() { synchronized (accounts) { accounts.clear(); - if (skCase == null) { - return; - } + } + if (skCase == null) { + return; + } - int artId = BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(); - int pathAttrId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID(); - String query = "SELECT value_text,blackboard_attributes.artifact_id,attribute_type_id " //NON-NLS - + "FROM blackboard_attributes,blackboard_artifacts WHERE " //NON-NLS - + "attribute_type_id=" + pathAttrId //NON-NLS - + " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //NON-NLS - + " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS + int artId = BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(); + int pathAttrId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID(); + String query = "SELECT value_text,blackboard_attributes.artifact_id,attribute_type_id " //NON-NLS + + "FROM blackboard_attributes,blackboard_artifacts WHERE " //NON-NLS + + "attribute_type_id=" + pathAttrId //NON-NLS + + " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //NON-NLS + + " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS - try (CaseDbQuery dbQuery = skCase.executeQuery(query)) { - ResultSet resultSet = dbQuery.getResultSet(); + try (CaseDbQuery dbQuery = skCase.executeQuery(query)) { + ResultSet resultSet = dbQuery.getResultSet(); + synchronized (accounts) { while (resultSet.next()) { final String path = resultSet.getString("value_text"); //NON-NLS final long artifactId = resultSet.getLong("artifact_id"); //NON-NLS @@ -134,9 +136,9 @@ public class EmailExtracted implements AutopsyVisitableItem { } messages.add(artifactId); } - } catch (TskCoreException | SQLException ex) { - logger.log(Level.WARNING, "Cannot initialize email extraction: ", ex); //NON-NLS } + } catch (TskCoreException | SQLException ex) { + logger.log(Level.WARNING, "Cannot initialize email extraction: ", ex); //NON-NLS } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java index 41f3efc122..2264b95ac6 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java @@ -104,21 +104,23 @@ public class HashsetHits implements AutopsyVisitableItem { final void update() { synchronized (hashSetHitsMap) { hashSetHitsMap.clear(); + } - if (skCase == null) { - return; - } + if (skCase == null) { + return; + } - int setNameId = ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(); - int artId = ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(); - String query = "SELECT value_text,blackboard_attributes.artifact_id,attribute_type_id " //NON-NLS - + "FROM blackboard_attributes,blackboard_artifacts WHERE " //NON-NLS - + "attribute_type_id=" + setNameId //NON-NLS - + " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //NON-NLS - + " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS + int setNameId = ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(); + int artId = ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(); + String query = "SELECT value_text,blackboard_attributes.artifact_id,attribute_type_id " //NON-NLS + + "FROM blackboard_attributes,blackboard_artifacts WHERE " //NON-NLS + + "attribute_type_id=" + setNameId //NON-NLS + + " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //NON-NLS + + " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS - try (CaseDbQuery dbQuery = skCase.executeQuery(query)) { - ResultSet resultSet = dbQuery.getResultSet(); + try (CaseDbQuery dbQuery = skCase.executeQuery(query)) { + ResultSet resultSet = dbQuery.getResultSet(); + synchronized (hashSetHitsMap) { while (resultSet.next()) { String setName = resultSet.getString("value_text"); //NON-NLS long artifactId = resultSet.getLong("artifact_id"); //NON-NLS @@ -127,13 +129,13 @@ public class HashsetHits implements AutopsyVisitableItem { } hashSetHitsMap.get(setName).add(artifactId); } - } catch (TskCoreException | SQLException ex) { - logger.log(Level.WARNING, "SQL Exception occurred: ", ex); //NON-NLS } - - setChanged(); - notifyObservers(); + } catch (TskCoreException | SQLException ex) { + logger.log(Level.WARNING, "SQL Exception occurred: ", ex); //NON-NLS } + + setChanged(); + notifyObservers(); } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java index 8faec30ab7..b07f5568c0 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java @@ -64,20 +64,28 @@ public class InterestingHits implements AutopsyVisitableItem { private class InterestingResults extends Observable { + // NOTE: the map can be accessed by multiple worker threads and needs to be synchronized private final Map> interestingItemsMap = new LinkedHashMap<>(); public List getSetNames() { - List setNames = new ArrayList<>(interestingItemsMap.keySet()); + List setNames; + synchronized (interestingItemsMap) { + setNames = new ArrayList<>(interestingItemsMap.keySet()); + } Collections.sort(setNames); return setNames; } public Set getArtifactIds(String setName) { - return interestingItemsMap.get(setName); + synchronized (interestingItemsMap) { + return interestingItemsMap.get(setName); + } } public void update() { - interestingItemsMap.clear(); + synchronized (interestingItemsMap) { + interestingItemsMap.clear(); + } loadArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT); loadArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT); setChanged(); @@ -103,14 +111,16 @@ public class InterestingHits implements AutopsyVisitableItem { + " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS try (CaseDbQuery dbQuery = skCase.executeQuery(query)) { - ResultSet resultSet = dbQuery.getResultSet(); - while (resultSet.next()) { - String value = resultSet.getString("value_text"); //NON-NLS - long artifactId = resultSet.getLong("artifact_id"); //NON-NLS - if (!interestingItemsMap.containsKey(value)) { - interestingItemsMap.put(value, new HashSet<>()); + synchronized (interestingItemsMap) { + ResultSet resultSet = dbQuery.getResultSet(); + while (resultSet.next()) { + String value = resultSet.getString("value_text"); //NON-NLS + long artifactId = resultSet.getLong("artifact_id"); //NON-NLS + if (!interestingItemsMap.containsKey(value)) { + interestingItemsMap.put(value, new HashSet<>()); + } + interestingItemsMap.get(value).add(artifactId); } - interestingItemsMap.get(value).add(artifactId); } } catch (TskCoreException | SQLException ex) { logger.log(Level.WARNING, "SQL Exception occurred: ", ex); //NON-NLS From 4272c6f5a7a9c9e7d36083937f31604e18449497 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Tue, 28 Jun 2016 11:21:28 -0400 Subject: [PATCH 6/6] Added thread safety to KeywordResults class --- .../autopsy/datamodel/KeywordHits.java | 111 ++++++++++-------- 1 file changed, 60 insertions(+), 51 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java index 987cf72caa..319d9ecf9f 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java @@ -73,85 +73,94 @@ public class KeywordHits implements AutopsyVisitableItem { private final class KeywordResults extends Observable { // Map from listName/Type to Map of keyword to set of artifact Ids - private final Map>> topLevelMap; + // NOTE: the map can be accessed by multiple worker threads and needs to be synchronized + private final Map>> topLevelMap = new LinkedHashMap<>(); KeywordResults() { - topLevelMap = new LinkedHashMap<>(); update(); } List getListNames() { - List names = new ArrayList<>(topLevelMap.keySet()); - // this causes the "Single ..." terms to be in the middle of the results, - // which is wierd. Make a custom comparator or do something else to maek them on top - //Collections.sort(names); - return names; + synchronized (topLevelMap) { + List names = new ArrayList<>(topLevelMap.keySet()); + // this causes the "Single ..." terms to be in the middle of the results, + // which is wierd. Make a custom comparator or do something else to maek them on top + //Collections.sort(names); + return names; + } } List getKeywords(String listName) { - List keywords = new ArrayList<>(topLevelMap.get(listName).keySet()); + List keywords; + synchronized (topLevelMap) { + keywords = new ArrayList<>(topLevelMap.get(listName).keySet()); + } Collections.sort(keywords); return keywords; } Set getArtifactIds(String listName, String keyword) { - return topLevelMap.get(listName).get(keyword); + synchronized (topLevelMap) { + return topLevelMap.get(listName).get(keyword); + } } // populate maps based on artifactIds void populateMaps(Map> artifactIds) { - topLevelMap.clear(); + synchronized (topLevelMap) { + topLevelMap.clear(); - // map of list name to keword to artifact IDs - Map>> listsMap = new LinkedHashMap<>(); + // map of list name to keword to artifact IDs + Map>> listsMap = new LinkedHashMap<>(); - // Map from from literal keyword to artifact IDs - Map> literalMap = new LinkedHashMap<>(); + // Map from from literal keyword to artifact IDs + Map> literalMap = new LinkedHashMap<>(); - // Map from regex keyword artifact IDs - Map> regexMap = new LinkedHashMap<>(); + // Map from regex keyword artifact IDs + Map> regexMap = new LinkedHashMap<>(); - // top-level nodes - topLevelMap.put(SIMPLE_LITERAL_SEARCH, literalMap); - topLevelMap.put(SIMPLE_REGEX_SEARCH, regexMap); + // top-level nodes + topLevelMap.put(SIMPLE_LITERAL_SEARCH, literalMap); + topLevelMap.put(SIMPLE_REGEX_SEARCH, regexMap); - for (Map.Entry> art : artifactIds.entrySet()) { - long id = art.getKey(); - Map attributes = art.getValue(); + for (Map.Entry> art : artifactIds.entrySet()) { + long id = art.getKey(); + Map attributes = art.getValue(); - // I think we can use attributes.remove(...) here? - String listName = attributes.get(Long.valueOf(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID())); - String word = attributes.get(Long.valueOf(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID())); - String reg = attributes.get(Long.valueOf(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID())); + // I think we can use attributes.remove(...) here? + String listName = attributes.get(Long.valueOf(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID())); + String word = attributes.get(Long.valueOf(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID())); + String reg = attributes.get(Long.valueOf(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID())); - // part of a list - if (listName != null) { - if (listsMap.containsKey(listName) == false) { - listsMap.put(listName, new LinkedHashMap>()); + // part of a list + if (listName != null) { + if (listsMap.containsKey(listName) == false) { + listsMap.put(listName, new LinkedHashMap>()); + } + + Map> listMap = listsMap.get(listName); + if (listMap.containsKey(word) == false) { + listMap.put(word, new HashSet()); + } + + listMap.get(word).add(id); + } // regular expression, single term + else if (reg != null) { + if (regexMap.containsKey(reg) == false) { + regexMap.put(reg, new HashSet()); + } + regexMap.get(reg).add(id); + } // literal, single term + else { + if (literalMap.containsKey(word) == false) { + literalMap.put(word, new HashSet()); + } + literalMap.get(word).add(id); } - - Map> listMap = listsMap.get(listName); - if (listMap.containsKey(word) == false) { - listMap.put(word, new HashSet()); - } - - listMap.get(word).add(id); - } // regular expression, single term - else if (reg != null) { - if (regexMap.containsKey(reg) == false) { - regexMap.put(reg, new HashSet()); - } - regexMap.get(reg).add(id); - } // literal, single term - else { - if (literalMap.containsKey(word) == false) { - literalMap.put(word, new HashSet()); - } - literalMap.get(word).add(id); + topLevelMap.putAll(listsMap); } - topLevelMap.putAll(listsMap); } - + setChanged(); notifyObservers(); }