diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesByTypeNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesByTypeNode.java index afeb99b8ec..6dae811e99 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesByTypeNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesByTypeNode.java @@ -22,7 +22,9 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.EnumSet; import java.util.List; +import java.util.Set; import java.util.logging.Level; +import java.util.stream.Collectors; import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; @@ -48,13 +50,23 @@ public class DataSourcesByTypeNode extends DisplayableItemNode { */ public static class DataSourcesByTypeChildren extends ChildFactory.Detachable { + private static final Set UPDATE_EVTS = EnumSet.of( + Case.Events.DATA_SOURCE_ADDED, + Case.Events.HOSTS_ADDED, + Case.Events.HOSTS_DELETED, + Case.Events.HOSTS_CHANGED); + + private static final Set UPDATE_EVT_STRS = UPDATE_EVTS.stream() + .map(evt -> evt.name()) + .collect(Collectors.toSet()); + private static final Logger logger = Logger.getLogger(DataSourcesByTypeChildren.class.getName()); private final PropertyChangeListener pcl = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { String eventType = evt.getPropertyName(); - if (eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { + if (UPDATE_EVT_STRS.contains(eventType)) { refresh(true); } } @@ -62,12 +74,12 @@ public class DataSourcesByTypeNode extends DisplayableItemNode { @Override protected void addNotify() { - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED), pcl); + Case.addEventTypeSubscriber(UPDATE_EVTS, pcl); } @Override protected void removeNotify() { - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED), pcl); + Case.removeEventTypeSubscriber(UPDATE_EVTS, pcl); } @Override @@ -91,7 +103,7 @@ public class DataSourcesByTypeNode extends DisplayableItemNode { } } - + private static final String NAME = Bundle.DataSourcesHostsNode_name(); /** @@ -100,7 +112,7 @@ public class DataSourcesByTypeNode extends DisplayableItemNode { public static String getNameIdentifier() { return NAME; } - + /** * Main constructor. */ diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/OsAccounts.java b/Core/src/org/sleuthkit/autopsy/datamodel/OsAccounts.java index 8fd5bfb84d..df0d1968aa 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/OsAccounts.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/OsAccounts.java @@ -24,6 +24,7 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.EnumSet; import java.util.List; import java.util.Optional; import java.util.logging.Level; @@ -52,7 +53,7 @@ public final class OsAccounts implements AutopsyVisitableItem { private static final String ICON_PATH = "org/sleuthkit/autopsy/images/os-account.png"; private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); - private final SleuthkitCase skCase; + private SleuthkitCase skCase; private final long filteringDSObjId; public OsAccounts(SleuthkitCase skCase) { @@ -112,34 +113,46 @@ public final class OsAccounts implements AutopsyVisitableItem { private final PropertyChangeListener listener = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { - refresh(true); + String eventType = evt.getPropertyName(); + if(eventType.equals(Case.Events.OS_ACCOUNT_ADDED.toString())) { + refresh(true); + } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { + // case was closed. Remove listeners so that we don't get called with a stale case handle + if (evt.getNewValue() == null) { + removeNotify(); + skCase = null; + } + } } }; @Override protected void addNotify() { Case.addEventTypeSubscriber(Collections.singleton(Case.Events.OS_ACCOUNT_ADDED), listener); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), listener); } @Override protected void removeNotify() { Case.removeEventTypeSubscriber(Collections.singleton(Case.Events.OS_ACCOUNT_ADDED), listener); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), listener); } @Override protected boolean createKeys(List list) { - try { - if (filteringDSObjId == 0) { - list.addAll(skCase.getOsAccountManager().getAccounts()); - } else { - Host host = skCase.getHostManager().getHost(skCase.getDataSource(filteringDSObjId)); - list.addAll(skCase.getOsAccountManager().getAccounts(host)); + if(skCase != null) { + try { + if (filteringDSObjId == 0) { + list.addAll(skCase.getOsAccountManager().getAccounts()); + } else { + Host host = skCase.getHostManager().getHost(skCase.getDataSource(filteringDSObjId)); + list.addAll(skCase.getOsAccountManager().getAccounts(host)); + } + } catch (TskCoreException | TskDataException ex) { + logger.log(Level.SEVERE, "Unable to retrieve list of OsAccounts for case", ex); + return false; } - } catch (TskCoreException | TskDataException ex) { - logger.log(Level.SEVERE, "Unable to retrieve list of OsAccounts for case", ex); - return false; } - return true; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/aleap-artifact-attribute-reference.xml b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/aleap-artifact-attribute-reference.xml index eb652a5b85..6b4ec13fdc 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/aleap-artifact-attribute-reference.xml +++ b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/aleap-artifact-attribute-reference.xml @@ -48,7 +48,7 @@ - + @@ -66,13 +66,13 @@ - - + + - + @@ -90,7 +90,7 @@ - + @@ -120,7 +120,7 @@ - + @@ -163,13 +163,13 @@ - - + + - + @@ -209,7 +209,7 @@ - + @@ -225,7 +225,7 @@ - + @@ -236,13 +236,13 @@ - - + + - + @@ -282,7 +282,7 @@ - + @@ -318,7 +318,7 @@ - + @@ -333,7 +333,7 @@ - + @@ -482,10 +482,10 @@ - + - - + + diff --git a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ileap-artifact-attribute-reference.xml b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ileap-artifact-attribute-reference.xml index 5799161685..16409f42c7 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ileap-artifact-attribute-reference.xml +++ b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ileap-artifact-attribute-reference.xml @@ -72,7 +72,7 @@ - + @@ -237,8 +237,8 @@ - - + + @@ -252,17 +252,15 @@ - - - - + + + + - - @@ -314,9 +312,9 @@ - - - + + + @@ -357,7 +355,7 @@ - + @@ -377,7 +375,7 @@ - + @@ -495,13 +493,6 @@ - - - - - - - @@ -524,7 +515,7 @@ - + @@ -543,14 +534,12 @@ - + - - @@ -714,13 +703,14 @@ - + - + + - + @@ -741,13 +731,13 @@ - + - + - + diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java index 9513163587..4ecb35a455 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java @@ -192,12 +192,15 @@ public final class ImageGalleryController { * @param theCase The case. */ static void shutDownController(Case theCase) { + ImageGalleryController controller = null; synchronized (controllersByCaseLock) { if (controllersByCase.containsKey(theCase.getName())) { - ImageGalleryController controller = controllersByCase.remove(theCase.getName()); - controller.shutDown(); + controller = controllersByCase.remove(theCase.getName()); } } + if (controller != null) { + controller.shutDown(); + } } /** diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java index 112c7ab6ec..e520e2d0ec 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java @@ -100,13 +100,9 @@ public abstract class DrawableFile { private String model; - private final CategoryManager categoryManager; - protected DrawableFile(AbstractFile file, Boolean analyzed) { this.analyzed = new SimpleBooleanProperty(analyzed); this.file = file; - - categoryManager = ImageGalleryController.getController(Case.getCurrentCase()).getCategoryManager(); } public abstract boolean isVideo(); @@ -245,13 +241,19 @@ public abstract class DrawableFile { /** * Update the category property. */ - private void updateCategory() { + private void updateCategory() { try { + ImageGalleryController controllerForCase = ImageGalleryController.getController(Case.getCurrentCaseThrows()); + if (controllerForCase == null) { + // This can only happen during case closing, so return without generating an error. + return; + } + List contentTags = getContentTags(); TagName tag = null; for (ContentTag ct : contentTags) { TagName tagName = ct.getName(); - if (categoryManager.isCategoryTagName(tagName)) { + if (controllerForCase.getCategoryManager().isCategoryTagName(tagName)) { tag = tagName; break; } @@ -259,7 +261,7 @@ public abstract class DrawableFile { categoryTagName.set(tag); } catch (TskCoreException ex) { LOGGER.log(Level.WARNING, "problem looking up category for " + this.getContentPathSafe(), ex); //NON-NLS - } catch (IllegalStateException ex) { + } catch (IllegalStateException | NoCurrentCaseException ex) { // We get here many times if the case is closed during ingest, so don't print out a ton of warnings. } } diff --git a/test/script/tskdbdiff.py b/test/script/tskdbdiff.py index 85087892b1..9452b335d9 100644 --- a/test/script/tskdbdiff.py +++ b/test/script/tskdbdiff.py @@ -444,6 +444,7 @@ def normalize_db_entry(line, files_table, vs_parts_table, vs_info_table, fs_info ig_groups_seen_index = line.find('INSERT INTO "image_gallery_groups_seen"') > -1 or line.find('INSERT INTO image_gallery_groups_seen ') > -1 os_account_index = line.find('INSERT INTO "tsk_os_accounts"') > -1 or line.find('INSERT INTO tsk_os_accounts') > -1 os_account_attr_index = line.find('INSERT INTO "tsk_os_account_attributes"') > -1 or line.find('INSERT INTO tsk_os_account_attributes') > -1 + os_account_instances_index = line.find('INSERT INTO "tsk_os_account_instances"') > -1 or line.find('INSERT INTO tsk_os_account_instances') > -1 parens = line[line.find('(') + 1 : line.rfind(')')] no_space_parens = parens.replace(" ", "") @@ -664,6 +665,11 @@ def normalize_db_entry(line, files_table, vs_parts_table, vs_info_table, fs_info fields_list[3] = "NULL" newLine = ('INSERT INTO "tsk_os_account_attributes" VALUES(' + ','.join(fields_list[1:]) + ');') # remove id return newLine + elif os_account_instances_index: + os_account_id = int(fields_list[1]) + fields_list[1] = accounts_table[os_account_id] + newLine = ('INSERT INTO "tsk_os_account_instances" VALUES(' + ','.join(fields_list[1:]) + ');') # remove id + return newLine else: return line