From 8cf931603506a2b29577249616cacaafc0eddfd8 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Tue, 16 Jun 2015 16:23:43 -0400 Subject: [PATCH 1/3] Add checks for nulls due to closed case --- .../autopsy/datamodel/DeletedContent.java | 37 +++- .../autopsy/datamodel/EmailExtracted.java | 44 ++++- .../autopsy/datamodel/ExtractedContent.java | 80 +++++++-- .../sleuthkit/autopsy/datamodel/FileSize.java | 37 +++- .../autopsy/datamodel/FileTypesNode.java | 27 ++- .../autopsy/datamodel/HashsetHits.java | 46 ++++- .../autopsy/datamodel/InterestingHits.java | 117 ++++++++----- .../autopsy/datamodel/KeywordHits.java | 44 ++++- .../sleuthkit/autopsy/datamodel/Reports.java | 15 +- .../org/sleuthkit/autopsy/datamodel/Tags.java | 158 +++++++++++------- .../DirectoryTreeTopComponent.java | 43 +++-- .../autopsy/events/RemoteEventPublisher.java | 20 ++- .../autopsy/filesearch/DateSearchFilter.java | 19 ++- .../autopsy/ingest/IngestManager.java | 2 +- .../ingest/events/BlackboardPostEvent.java | 2 +- .../autopsy/timeline/TimeLineController.java | 38 ++++- 16 files changed, 549 insertions(+), 180 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java index 37f7140d37..abcade50e1 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java @@ -183,13 +183,38 @@ public class DeletedContent implements AutopsyVisitableItem { // new file was added if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) { - // @@@ COULD CHECK If the new file is deleted before notifying... - update(); + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. + * Currently, remote events may be received for a case + * that is already closed. + */ + try { + Case.getCurrentCase(); + // @@@ COULD CHECK If the new file is deleted before notifying... + update(); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) - || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { - update(); - } else if (eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { - update(); + || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) + || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. + * Currently, remote events may be received for a case + * that is already closed. + */ + try { + Case.getCurrentCase(); + update(); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } } 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) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java index 4f59c3a52b..519a018821 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java @@ -204,15 +204,45 @@ public class EmailExtracted implements AutopsyVisitableItem { @Override public void propertyChange(PropertyChangeEvent evt) { String eventType = evt.getPropertyName(); - if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) { - if (((ModuleDataEvent) evt.getOldValue()).getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG) { - emailResults.update(); + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. Currently, + * remote events may be received for a case that is already + * closed. + */ + try { + Case.getCurrentCase(); + /** + * Due to some unresolved issues with how cases are + * closed, it is possible for the event to have a null + * oldValue if the event is a remote event. + */ + ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue(); + if (null != eventData && eventData.getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG) { + emailResults.update(); + } + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } + } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) + || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. Currently, + * remote events may be received for a case that is already + * closed. + */ + try { + Case.getCurrentCase(); + emailResults.update(); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ } - } - else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) - || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { - emailResults.update(); } 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 diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java index 1b8966f5e6..85c87adc10 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java @@ -147,15 +147,45 @@ public class ExtractedContent implements AutopsyVisitableItem { @Override public void propertyChange(PropertyChangeEvent evt) { String eventType = evt.getPropertyName(); - if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) { - final ModuleDataEvent event = (ModuleDataEvent) evt.getOldValue(); - if (doNotShow.contains(event.getArtifactType()) == false) { - refresh(true); + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. Currently, + * remote events may be received for a case that is already + * closed. + */ + try { + Case.getCurrentCase(); + /** + * Due to some unresolved issues with how cases are + * closed, it is possible for the event to have a null + * oldValue if the event is a remote event. + */ + final ModuleDataEvent event = (ModuleDataEvent) evt.getOldValue(); + if (null != event && doNotShow.contains(event.getArtifactType()) == false) { + refresh(true); + } + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ } } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { - refresh(true); + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. Currently, + * remote events may be received for a case that is already + * closed. + */ + try { + Case.getCurrentCase(); + refresh(true); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } } 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 @@ -362,15 +392,45 @@ public class ExtractedContent implements AutopsyVisitableItem { @Override public void propertyChange(PropertyChangeEvent evt) { String eventType = evt.getPropertyName(); - if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) { - final ModuleDataEvent event = (ModuleDataEvent) evt.getOldValue(); - if (event.getArtifactType() == type) { - refresh(true); + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. Currently, + * remote events may be received for a case that is already + * closed. + */ + try { + Case.getCurrentCase(); + /** + * Due to some unresolved issues with how cases are + * closed, it is possible for the event to have a null + * oldValue if the event is a remote event. + */ + final ModuleDataEvent event = (ModuleDataEvent) evt.getOldValue(); + if (null != event && event.getArtifactType() == type) { + refresh(true); + } + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ } } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { - refresh(true); + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. Currently, + * remote events may be received for a case that is already + * closed. + */ + try { + Case.getCurrentCase(); + refresh(true); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } } } }; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java index e6f32e1ef2..4b4659aa94 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java @@ -180,13 +180,38 @@ public class FileSize implements AutopsyVisitableItem { // new file was added if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) { - // @@@ could check the size here and only fire off updates if we know the file meets the min size criteria - update(); + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. + * Currently, remote events may be received for a case + * that is already closed. + */ + try { + // @@@ could check the size here and only fire off updates if we know the file meets the min size criteria + Case.getCurrentCase(); + update(); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) - || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { - update(); - } else if (eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { - update(); + || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) + || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. + * Currently, remote events may be received for a case + * that is already closed. + */ + try { + Case.getCurrentCase(); + update(); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } } 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) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java index f9e583d45a..d230725410 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java @@ -152,15 +152,24 @@ public class FileTypesNode extends DisplayableItemNode { @Override public void propertyChange(PropertyChangeEvent evt) { String eventType = evt.getPropertyName(); - - // new file was added - if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) { - update(); - } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) - || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { - update(); - } else if (eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { - update(); + if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString()) + || eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) + || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) + || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. + * Currently, remote events may be received for a case + * that is already closed. + */ + try { + Case.getCurrentCase(); + update(); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } } 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) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java index f893c1e5b3..928ba3c5f2 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java @@ -180,16 +180,46 @@ public class HashsetHits implements AutopsyVisitableItem { private final PropertyChangeListener pcl = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { - String eventType = evt.getPropertyName(); - + String eventType = evt.getPropertyName(); if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) { - if (((ModuleDataEvent) evt.getOldValue()).getArtifactType() == ARTIFACT_TYPE.TSK_HASHSET_HIT) { - hashsetResults.update(); + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. Currently, + * remote events may be received for a case that is already + * closed. + */ + try { + Case.getCurrentCase(); + /** + * Due to some unresolved issues with how cases are + * closed, it is possible for the event to have a null + * oldValue if the event is a remote event. + */ + ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue(); + if (null != eventData && eventData.getArtifactType() == ARTIFACT_TYPE.TSK_HASHSET_HIT) { + hashsetResults.update(); + } + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } + } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) + || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. Currently, + * remote events may be received for a case that is already + * closed. + */ + try { + Case.getCurrentCase(); + hashsetResults.update(); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ } - } - else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) - || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { - hashsetResults.update(); } 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 diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java index 76e9c1c836..4a476231ad 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.datamodel; - import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.sql.ResultSet; @@ -50,34 +49,34 @@ import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery; import org.sleuthkit.datamodel.TskCoreException; - public class InterestingHits implements AutopsyVisitableItem { - + private static final String INTERESTING_ITEMS = NbBundle .getMessage(InterestingHits.class, "InterestingHits.interestingItems.text"); private static final String DISPLAY_NAME = NbBundle.getMessage(InterestingHits.class, "InterestingHits.displayName.text"); private static final Logger logger = Logger.getLogger(InterestingHits.class.getName()); private SleuthkitCase skCase; private final InterestingResults interestingResults = new InterestingResults(); - + public InterestingHits(SleuthkitCase skCase) { this.skCase = skCase; interestingResults.update(); } - + private class InterestingResults extends Observable { + private final Map> interestingItemsMap = new LinkedHashMap<>(); - + public List getSetNames() { List setNames = new ArrayList<>(interestingItemsMap.keySet()); Collections.sort(setNames); return setNames; } - + public Set getArtifactIds(String setName) { return interestingItemsMap.get(setName); } - + public void update() { interestingItemsMap.clear(); loadArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT); @@ -85,16 +84,17 @@ public class InterestingHits implements AutopsyVisitableItem { setChanged(); notifyObservers(); } - + /* - * Reads the artifacts of specified type, grouped by Set, and loads into the interestingItemsMap + * Reads the artifacts of specified type, grouped by Set, and loads into + * the interestingItemsMap */ @SuppressWarnings("deprecation") private void loadArtifacts(BlackboardArtifact.ARTIFACT_TYPE artType) { if (skCase == null) { - return; + return; } - + int setNameId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(); int artId = artType.getTypeID(); String query = "SELECT value_text,blackboard_attributes.artifact_id,attribute_type_id " //NON-NLS @@ -118,13 +118,13 @@ public class InterestingHits implements AutopsyVisitableItem { } } } - + @Override public T accept(AutopsyItemVisitor v) { return v.visit(this); } - - /** + + /** * Node for the interesting items */ public class RootNode extends DisplayableItemNode { @@ -140,7 +140,7 @@ public class InterestingHits implements AutopsyVisitableItem { public boolean isLeafTypeNode() { return false; } - + @Override public T accept(DisplayableItemNodeVisitor v) { return v.visit(this); @@ -156,36 +156,66 @@ public class InterestingHits implements AutopsyVisitableItem { } ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"), - NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.displayName"), - NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.desc"), - getName())); + NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.displayName"), + NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.desc"), + getName())); return s; } } - - private class SetNameFactory extends ChildFactory.Detachable implements Observer { - /* This should probably be in the top-level class, but the factory has nice methods - * for its startup and shutdown, so it seemed like a cleaner place to register the - * property change listener. + private class SetNameFactory extends ChildFactory.Detachable implements Observer { + + /* + * This should probably be in the top-level class, but the factory has + * nice methods for its startup and shutdown, so it seemed like a + * cleaner place to register the property change listener. */ private final PropertyChangeListener pcl = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { String eventType = evt.getPropertyName(); - if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) { - if ((((ModuleDataEvent) evt.getOldValue()).getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT) || - (((ModuleDataEvent) evt.getOldValue()).getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT)) { - interestingResults.update(); + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. Currently, + * remote events may be received for a case that is already + * closed. + */ + try { + Case.getCurrentCase(); + /** + * Due to some unresolved issues with how cases are + * closed, it is possible for the event to have a null + * oldValue if the event is a remote event. + */ + ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue(); + if (null != eventData && (eventData.getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT + || eventData.getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT)) { + interestingResults.update(); + } + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ } - } - else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) - || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { - interestingResults.update(); - } - else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { + } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) + || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. Currently, + * remote events may be received for a case that is already + * closed. + */ + try { + Case.getCurrentCase(); + interestingResults.update(); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } + } 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(); @@ -211,7 +241,7 @@ public class InterestingHits implements AutopsyVisitableItem { Case.removePropertyChangeListener(pcl); interestingResults.deleteObserver(this); } - + @Override protected boolean createKeys(List list) { list.addAll(interestingResults.getSetNames()); @@ -228,9 +258,11 @@ public class InterestingHits implements AutopsyVisitableItem { refresh(true); } } - + public class SetNameNode extends DisplayableItemNode implements Observer { + private final String setName; + public SetNameNode(String setName) {//, Set children) { super(Children.create(new HitFactory(setName), true), Lookups.singleton(setName)); this.setName = setName; @@ -239,7 +271,7 @@ public class InterestingHits implements AutopsyVisitableItem { this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/interesting_item.png"); //NON-NLS interestingResults.addObserver(this); } - + private void updateDisplayName() { super.setDisplayName(setName + " (" + interestingResults.getArtifactIds(setName).size() + ")"); } @@ -259,9 +291,9 @@ public class InterestingHits implements AutopsyVisitableItem { } ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"), - NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"), - NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.desc"), - getName())); + NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"), + NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.desc"), + getName())); return s; } @@ -276,8 +308,9 @@ public class InterestingHits implements AutopsyVisitableItem { updateDisplayName(); } } - + private class HitFactory extends ChildFactory implements Observer { + private final String setName; private HitFactory(String setName) { @@ -297,7 +330,7 @@ public class InterestingHits implements AutopsyVisitableItem { @Override protected Node createNodeForKey(Long l) { if (skCase == null) { - return null; + return null; } try { return new BlackboardArtifactNode(skCase.getBlackboardArtifact(l)); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java index d1e7bce138..44c530251e 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java @@ -246,15 +246,45 @@ public class KeywordHits implements AutopsyVisitableItem { @Override public void propertyChange(PropertyChangeEvent evt) { String eventType = evt.getPropertyName(); - if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) { - if (((ModuleDataEvent) evt.getOldValue()).getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT) { - keywordResults.update(); + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. Currently, + * remote events may be received for a case that is already + * closed. + */ + try { + Case.getCurrentCase(); + /** + * Due to some unresolved issues with how cases are + * closed, it is possible for the event to have a null + * oldValue if the event is a remote event. + */ + ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue(); + if (null != eventData && eventData.getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT) { + keywordResults.update(); + } + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } + } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) + || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. Currently, + * remote events may be received for a case that is already + * closed. + */ + try { + Case.getCurrentCase(); + keywordResults.update(); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ } - } - else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) - || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { - keywordResults.update(); } 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 diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Reports.java b/Core/src/org/sleuthkit/autopsy/datamodel/Reports.java index 9822227d7a..83a2772bda 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Reports.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Reports.java @@ -98,7 +98,20 @@ public final class Reports implements AutopsyVisitableItem { public void propertyChange(PropertyChangeEvent evt) { String eventType = evt.getPropertyName(); if (eventType.equals(Case.Events.REPORT_ADDED.toString())) { - ReportNodeFactory.this.refresh(true); + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. + * Currently, remote events may be received for a case + * that is already closed. + */ + try { + Case.getCurrentCase(); + ReportNodeFactory.this.refresh(true); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } } } }); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index cc7958355e..9894aa32fb 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -51,26 +51,23 @@ public class Tags implements AutopsyVisitableItem { // Creation of a RootNode object corresponding to a Tags object is done // by a CreateAutopsyNodeVisitor dispatched from the AbstractContentChildren // override of Children.Keys.createNodes(). - + private final TagResults tagResults = new TagResults(); private final String DISPLAY_NAME = NbBundle.getMessage(RootNode.class, "TagsNode.displayName.text"); private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS - @Override public T accept(AutopsyItemVisitor v) { return v.visit(this); } - - - /** - * This class largely does nothing except act as a top-level object that - * the other nodes can listen to. This mimics what other nodes have (keword search, etc.), - * but theirs stores data. + * This class largely does nothing except act as a top-level object that the + * other nodes can listen to. This mimics what other nodes have (keword + * search, etc.), but theirs stores data. */ private class TagResults extends Observable { + public void update() { setChanged(); notifyObservers(); @@ -123,20 +120,55 @@ public class Tags implements AutopsyVisitableItem { public void propertyChange(PropertyChangeEvent evt) { String eventType = evt.getPropertyName(); if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) { - /* Note: this is a hack. In an ideal world, TagsManager - * would fire events so that the directory tree would - * refresh. But, we haven't had a chance to add that so, we - * fire these events and the tree refreshes based on them. */ - if ((((ModuleDataEvent) evt.getOldValue()).getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT) - || ((ModuleDataEvent) evt.getOldValue()).getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE) { - refresh(true); - tagResults.update(); + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. Currently, + * remote events may be received for a case that is already + * closed. + */ + try { + Case.getCurrentCase(); + /** + * There are two things to note here. It is possible for + * the event to have a null oldValue if the event is a + * remote event and the case is closed after the above + * call, but before this code executes. Second, the use + * of deprecated artifact types here is explained by the + * fact that in an ideal world, the TagsManager would + * fire tag-related events so that the tags tree would + * refresh. But, we haven't had a chance to add that, so + * we fire these events with bogus artifacts to indicate + * a tree refresh is required. + */ + ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue(); + if (null != eventData + && (eventData.getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT + || eventData.getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE)) { + refresh(true); + tagResults.update(); + } + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ } } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { - refresh(true); - tagResults.update(); - } - else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. Currently, + * remote events may be received for a case that is already + * closed. + */ + try { + Case.getCurrentCase(); + refresh(true); + tagResults.update(); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } + } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { // case was closed. Remove listeners so that this can be garbage collected if (evt.getNewValue() == null) { removeNotify(); @@ -187,15 +219,15 @@ public class Tags implements AutopsyVisitableItem { /** * Instances of this class are elements of Node hierarchies consisting of - * content and blackboard artifact tags, grouped first by tag type, then by tag - * name. + * content and blackboard artifact tags, grouped first by tag type, then by + * tag name. */ public class TagNameNode extends DisplayableItemNode implements Observer { private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS private final String BOOKMARK_TAG_ICON_PATH = "org/sleuthkit/autopsy/images/star-bookmark-icon-16.png"; //NON-NLS private final TagName tagName; - + public TagNameNode(TagName tagName) { super(Children.create(new TagTypeNodeFactory(tagName), true), Lookups.singleton(NbBundle.getMessage(TagNameNode.class, "TagNameNode.namePlusTags.text", tagName.getDisplayName()))); this.tagName = tagName; @@ -250,12 +282,13 @@ public class Tags implements AutopsyVisitableItem { updateDisplayName(); } } - + /** - * Creates nodes for the two types of tags: file and artifact. - * Does not need observer / messages since it always has the same children + * Creates nodes for the two types of tags: file and artifact. Does not need + * observer / messages since it always has the same children */ private class TagTypeNodeFactory extends ChildFactory { + private final TagName tagName; private final String CONTENT_TAG_TYPE_NODE_KEY = NbBundle.getMessage(TagNameNode.class, "TagNameNode.contentTagTypeNodeKey.text"); private final String BLACKBOARD_ARTIFACT_TAG_TYPE_NODE_KEY = NbBundle.getMessage(TagNameNode.class, "TagNameNode.bbArtTagTypeNodeKey.text"); @@ -284,19 +317,20 @@ public class Tags implements AutopsyVisitableItem { } } } - + private final String CONTENT_DISPLAY_NAME = NbBundle.getMessage(ContentTagTypeNode.class, "ContentTagTypeNode.displayName.text"); - + /** - * Node for the content tags. Children are specific tags. - * Instances of this class are are elements of a directory tree sub-tree - * consisting of content and blackboard artifact tags, grouped first by tag - * type, then by tag name. + * Node for the content tags. Children are specific tags. Instances of this + * class are are elements of a directory tree sub-tree consisting of content + * and blackboard artifact tags, grouped first by tag type, then by tag + * name. */ public class ContentTagTypeNode extends DisplayableItemNode implements Observer { private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS private TagName tagName; + public ContentTagTypeNode(TagName tagName) { super(Children.create(new ContentTagNodeFactory(tagName), true), Lookups.singleton(tagName.getDisplayName() + " " + CONTENT_DISPLAY_NAME)); this.tagName = tagName; @@ -305,7 +339,7 @@ public class Tags implements AutopsyVisitableItem { this.setIconBaseWithExtension(ICON_PATH); tagResults.addObserver(this); } - + private void updateDisplayName() { long tagsCount = 0; try { @@ -341,10 +375,11 @@ public class Tags implements AutopsyVisitableItem { @Override public void update(Observable o, Object arg) { updateDisplayName(); - } + } } - + private class ContentTagNodeFactory extends ChildFactory implements Observer { + private final TagName tagName; ContentTagNodeFactory(TagName tagName) { @@ -377,13 +412,15 @@ public class Tags implements AutopsyVisitableItem { } private final String ARTIFACT_DISPLAY_NAME = NbBundle.getMessage(BlackboardArtifactTagTypeNode.class, "BlackboardArtifactTagTypeNode.displayName.text"); - + /** * Instances of this class are elements in a sub-tree of the Autopsy - * presentation of the SleuthKit data model. The sub-tree consists of content - * and blackboard artifact tags, grouped first by tag type, then by tag name. + * presentation of the SleuthKit data model. The sub-tree consists of + * content and blackboard artifact tags, grouped first by tag type, then by + * tag name. */ public class BlackboardArtifactTagTypeNode extends DisplayableItemNode implements Observer { + private TagName tagName; private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS @@ -395,7 +432,7 @@ public class Tags implements AutopsyVisitableItem { updateDisplayName(); tagResults.addObserver(this); } - + private void updateDisplayName() { long tagsCount = 0; try { @@ -435,28 +472,29 @@ public class Tags implements AutopsyVisitableItem { } private class BlackboardArtifactTagNodeFactory extends ChildFactory { - private final TagName tagName; - BlackboardArtifactTagNodeFactory(TagName tagName) { - super(); - this.tagName = tagName; - } + private final TagName tagName; - @Override - protected boolean createKeys(List keys) { - try { - // Use the blackboard artifact tags bearing the specified tag name as the keys. - keys.addAll(Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName)); - } catch (TskCoreException ex) { - Logger.getLogger(BlackboardArtifactTagNodeFactory.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS - } - return true; - } + BlackboardArtifactTagNodeFactory(TagName tagName) { + super(); + this.tagName = tagName; + } - @Override - protected Node createNodeForKey(BlackboardArtifactTag key) { - // The blackboard artifact tags to be wrapped are used as the keys. - return new BlackboardArtifactTagNode(key); - } - } + @Override + protected boolean createKeys(List keys) { + try { + // Use the blackboard artifact tags bearing the specified tag name as the keys. + keys.addAll(Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName)); + } catch (TskCoreException ex) { + Logger.getLogger(BlackboardArtifactTagNodeFactory.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS + } + return true; + } + + @Override + protected Node createNodeForKey(BlackboardArtifactTag key) { + // The blackboard artifact tags to be wrapped are used as the keys. + return new BlackboardArtifactTagNode(key); + } + } } diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index 3ce5709ce5..bd07ac054b 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -525,8 +525,6 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat @Override public void propertyChange(PropertyChangeEvent evt) { String changed = evt.getPropertyName(); - Object oldValue = evt.getOldValue(); - Object newValue = evt.getNewValue(); if (changed.equals(Case.Events.CURRENT_CASE.toString())) { // changed current case // When a case is closed, the old value of this property is the // closed Case object and the new value is null. When a case is @@ -536,15 +534,15 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat // opened events instead of property change events would be a better // solution. Either way, more probably needs to be done to clean up // data model objects when a case is closed. - if (oldValue != null && newValue == null) { + if (evt.getOldValue() != null && evt.getNewValue() == null) { // The current case has been closed. Reset the ExplorerManager. SwingUtilities.invokeLater(() -> { Node emptyNode = new AbstractNode(Children.LEAF); em.setRootContext(emptyNode); }); - } else if (newValue != null) { + } else if (evt.getNewValue() != null) { // A new case has been opened. Reset the ExplorerManager. - Case newCase = (Case) newValue; + Case newCase = (Case) evt.getNewValue(); final String newCaseName = newCase.getName(); SwingUtilities.invokeLater(() -> { em.getRootContext().setName(newCaseName); @@ -561,23 +559,44 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat } } // if the image is added to the case else if (changed.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { - if (IngestManager.getInstance().isRunningInteractively()) { + /** + * This is a stop gap measure until a different way of handling the + * closing of cases is worked out. Currently, remote events may be + * received for a case that is already closed. + */ + try { + Case.getCurrentCase(); CoreComponentControl.openCoreWindows(); + SwingUtilities.invokeLater(this::componentOpened); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ } - SwingUtilities.invokeLater(this::componentOpened); } // change in node selection else if (changed.equals(ExplorerManager.PROP_SELECTED_NODES)) { SwingUtilities.invokeLater(() -> { - respondSelection((Node[]) oldValue, (Node[]) newValue); + respondSelection((Node[]) evt.getOldValue(), (Node[]) evt.getNewValue()); }); } else if (changed.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) { // nothing to do here. // all nodes should be listening for these events and update accordingly. } else if (changed.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) - || changed.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { - SwingUtilities.invokeLater(this::refreshDataSourceTree); - } else if (changed.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) { - SwingUtilities.invokeLater(this::refreshDataSourceTree); + || changed.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) + || changed.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) { + /** + * This is a stop gap measure until a different way of handling the + * closing of cases is worked out. Currently, remote events may be + * received for a case that is already closed. + */ + try { + Case.getCurrentCase(); + SwingUtilities.invokeLater(this::refreshDataSourceTree); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } } } diff --git a/Core/src/org/sleuthkit/autopsy/events/RemoteEventPublisher.java b/Core/src/org/sleuthkit/autopsy/events/RemoteEventPublisher.java index ff144b39c6..c4cf9248c7 100644 --- a/Core/src/org/sleuthkit/autopsy/events/RemoteEventPublisher.java +++ b/Core/src/org/sleuthkit/autopsy/events/RemoteEventPublisher.java @@ -32,6 +32,7 @@ import javax.jms.ObjectMessage; import javax.jms.Session; import javax.jms.Topic; import org.apache.activemq.ActiveMQConnectionFactory; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; /** @@ -99,7 +100,7 @@ final class RemoteEventPublisher { } if (null != consumer) { consumer.close(); - } + } if (null != session) { session.close(); } @@ -134,6 +135,23 @@ final class RemoteEventPublisher { */ @Override public void onMessage(Message message) { + /** + * This is a stop gap measure until a different way of handling the + * closing of cases is worked out. Currently, Case.currentCase is + * set to null before Case.Event.CURRENT_CASE is published. That + * means that clients of this class have not had the chance to close + * their remote event channels and remote events may be received for + * a case that is already closed. + */ + try { + Case.getCurrentCase(); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do not publish the event. + */ + return; + } + try { if (message instanceof ObjectMessage) { ObjectMessage objectMessage = (ObjectMessage) message; diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchFilter.java b/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchFilter.java index f1df56f8ac..48b2e5d417 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchFilter.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchFilter.java @@ -74,7 +74,7 @@ class DateSearchFilter extends AbstractFileSearchFilter { public String getPredicate() throws FilterValidationException { String query = "NULL"; DateSearchPanel panel = this.getComponent(); - + // first, get the selected timeZone from the dropdown list String tz = this.getComponent().getTimeZoneComboBox().getSelectedItem().toString(); String tzID = tz.substring(tz.indexOf(" ") + 1); // 1 index after the space is the ID @@ -126,7 +126,7 @@ class DateSearchFilter extends AbstractFileSearchFilter { toDate = fromDate; fromDate = temp; } - + final boolean modifiedChecked = panel.getModifiedCheckBox().isSelected(); final boolean changedChecked = panel.getChangedCheckBox().isSelected(); final boolean accessedChecked = panel.getAccessedCheckBox().isSelected(); @@ -253,7 +253,20 @@ class DateSearchFilter extends AbstractFileSearchFilter { break; case DATA_SOURCE_ADDED: case DATA_SOURCE_DELETED: - SwingUtilities.invokeLater(DateSearchFilter.this::updateTimeZoneList); + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. Currently, + * remote events may be received for a case that is already + * closed. + */ + try { + Case.getCurrentCase(); + SwingUtilities.invokeLater(DateSearchFilter.this::updateTimeZoneList); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } break; } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index cb055fcb98..80eec14f1d 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -362,7 +362,7 @@ public class IngestManager { * ingest message box, NetBeans progress handles, etc. Running interactively * is the default. */ - public synchronized boolean isRunningInteractively() { + synchronized boolean isRunningInteractively() { return this.runInteractively; } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/events/BlackboardPostEvent.java b/Core/src/org/sleuthkit/autopsy/ingest/events/BlackboardPostEvent.java index 66a4296306..85fec5fb8f 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/events/BlackboardPostEvent.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/events/BlackboardPostEvent.java @@ -53,7 +53,7 @@ public final class BlackboardPostEvent extends AutopsyEvent implements Serializa */ public BlackboardPostEvent(ModuleDataEvent eventData) { /** - * Putting a serializable data holding object into newValue to allow for + * Putting a serializable data holding object into oldValue to allow for * lazy loading of the ModuleDataEvent object for remote events. This * bypasses the issues related to the serialization and de-serialization * of BlackboardArtifact objects when the event is published over a diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java index 703e5f0b0d..b5fcd7dc61 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java @@ -696,9 +696,22 @@ public class TimeLineController { switch (IngestManager.IngestJobEvent.valueOf(evt.getPropertyName())) { case CANCELLED: case COMPLETED: - SwingUtilities.invokeLater(() -> { - outOfDatePromptAndRebuild(); - }); + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. Currently, + * remote events may be received for a case that is already + * closed. + */ + try { + Case.getCurrentCase(); + SwingUtilities.invokeLater(() -> { + outOfDatePromptAndRebuild(); + }); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } break; } } @@ -711,9 +724,22 @@ public class TimeLineController { public void propertyChange(PropertyChangeEvent evt) { switch (Case.Events.valueOf(evt.getPropertyName())) { case DATA_SOURCE_ADDED: - SwingUtilities.invokeLater(() -> { - outOfDatePromptAndRebuild(); - }); + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. Currently, + * remote events may be received for a case that is already + * closed. + */ + try { + Case.getCurrentCase(); + SwingUtilities.invokeLater(() -> { + outOfDatePromptAndRebuild(); + }); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } break; case CURRENT_CASE: SwingUtilities.invokeLater(() -> { From e641d14f7e40ed47462e968e1353f902493e0d26 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 18 Jun 2015 11:54:40 -0400 Subject: [PATCH 2/3] Make IngestManager.isRunningINteractiveyl public again --- .../autopsy/datamodel/DeletedContent.java | 21 ++-- .../autopsy/datamodel/EmailExtracted.java | 30 ++--- .../autopsy/datamodel/ExtractedContent.java | 115 +++++++++--------- .../sleuthkit/autopsy/datamodel/FileSize.java | 20 +-- .../autopsy/datamodel/FileTypesNode.java | 10 +- .../autopsy/datamodel/HashsetHits.java | 23 ++-- .../autopsy/datamodel/InterestingHits.java | 25 ++-- .../autopsy/datamodel/KeywordHits.java | 28 ++--- .../sleuthkit/autopsy/datamodel/Reports.java | 10 +- .../org/sleuthkit/autopsy/datamodel/Tags.java | 29 ++--- .../DirectoryTreeTopComponent.java | 15 +-- .../autopsy/filesearch/DateSearchFilter.java | 8 +- .../autopsy/ingest/IngestManager.java | 2 +- .../autopsy/timeline/TimeLineController.java | 37 ++++-- 14 files changed, 192 insertions(+), 181 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java index abcade50e1..c32eb5c164 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2014 Basis Technology Corp. + * Copyright 2013-2015 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -180,17 +180,16 @@ public class DeletedContent implements AutopsyVisitableItem { @Override public void propertyChange(PropertyChangeEvent evt) { String eventType = evt.getPropertyName(); - - // new file was added if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) { /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. - * Currently, remote events may be received for a case - * that is already closed. + * Checking for a current case is a stop gap measure + * until a different way of handling the closing of + * cases is worked out. Currently, remote events may be + * received for a case that is already closed. */ try { Case.getCurrentCase(); + // new file was added // @@@ COULD CHECK If the new file is deleted before notifying... update(); } catch (IllegalStateException notUsed) { @@ -202,10 +201,10 @@ public class DeletedContent implements AutopsyVisitableItem { || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. - * Currently, remote events may be received for a case - * that is already closed. + * Checking for a current case is a stop gap measure + * until a different way of handling the closing of + * cases is worked out. Currently, remote events may be + * received for a case that is already closed. */ try { Case.getCurrentCase(); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java index 519a018821..abbb88def7 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java @@ -206,18 +206,19 @@ public class EmailExtracted implements AutopsyVisitableItem { String eventType = evt.getPropertyName(); if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) { /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. Currently, - * remote events may be received for a case that is already - * closed. + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked + * out. Currently, remote events may be received for a case + * that is already closed. */ try { Case.getCurrentCase(); - /** - * Due to some unresolved issues with how cases are - * closed, it is possible for the event to have a null - * oldValue if the event is a remote event. - */ + /** + * Even with the check above, it is still possible that the + * case will be closed in a different thread before this + * code executes. If that happens, it is possible for the + * event to have a null oldValue. + */ ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue(); if (null != eventData && eventData.getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG) { emailResults.update(); @@ -230,10 +231,10 @@ public class EmailExtracted implements AutopsyVisitableItem { } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. Currently, - * remote events may be received for a case that is already - * closed. + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked + * out. Currently, remote events may be received for a case + * that is already closed. */ try { Case.getCurrentCase(); @@ -243,8 +244,7 @@ public class EmailExtracted implements AutopsyVisitableItem { * Case is closed, do nothing. */ } - } - else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { + } 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(); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java index 85c87adc10..728b79fd87 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2014 Basis Technology Corp. + * Copyright 2011-2015 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -126,7 +126,7 @@ public class ExtractedContent implements AutopsyVisitableItem { * more specific form elsewhere in the tree. */ private class TypeFactory extends ChildFactory.Detachable { - private final ArrayList doNotShow; + private final ArrayList doNotShow = new ArrayList<>(); // maps the artifact type to its child node private final HashMap typeNodeList = new HashMap<>(); @@ -134,7 +134,6 @@ public class ExtractedContent implements AutopsyVisitableItem { super(); // these are shown in other parts of the UI tree - doNotShow = new ArrayList<>(); doNotShow.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO); doNotShow.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG); doNotShow.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT); @@ -143,56 +142,53 @@ public class ExtractedContent implements AutopsyVisitableItem { doNotShow.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT); } - private final PropertyChangeListener pcl = new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - String eventType = evt.getPropertyName(); - if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) { + private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> { + String eventType = evt.getPropertyName(); + if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) { + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. Currently, + * remote events may be received for a case that is already + * closed. + */ + try { + Case.getCurrentCase(); /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. Currently, - * remote events may be received for a case that is already - * closed. + * Due to some unresolved issues with how cases are + * closed, it is possible for the event to have a null + * oldValue if the event is a remote event. */ - try { - Case.getCurrentCase(); - /** - * Due to some unresolved issues with how cases are - * closed, it is possible for the event to have a null - * oldValue if the event is a remote event. - */ - final ModuleDataEvent event = (ModuleDataEvent) evt.getOldValue(); - if (null != event && doNotShow.contains(event.getArtifactType()) == false) { - refresh(true); - } - } catch (IllegalStateException notUsed) { - /** - * Case is closed, do nothing. - */ - } - } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) - || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { - /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. Currently, - * remote events may be received for a case that is already - * closed. - */ - try { - Case.getCurrentCase(); + final ModuleDataEvent event = (ModuleDataEvent) evt.getOldValue(); + if (null != event && doNotShow.contains(event.getArtifactType()) == false) { refresh(true); - } catch (IllegalStateException notUsed) { - /** - * Case is closed, do nothing. - */ } + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ } - 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; - } + } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) + || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { + /** + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. Currently, + * remote events may be received for a case that is already + * closed. + */ + try { + Case.getCurrentCase(); + refresh(true); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } + } + 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; } } }; @@ -394,17 +390,18 @@ public class ExtractedContent implements AutopsyVisitableItem { String eventType = evt.getPropertyName(); if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) { /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. Currently, - * remote events may be received for a case that is already - * closed. + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked + * out. Currently, remote events may be received for a case + * that is already closed. */ try { Case.getCurrentCase(); /** - * Due to some unresolved issues with how cases are - * closed, it is possible for the event to have a null - * oldValue if the event is a remote event. + * Even with the check above, it is still possible that + * the case will be closed in a different thread before + * this code executes. If that happens, it is possible + * for the event to have a null oldValue. */ final ModuleDataEvent event = (ModuleDataEvent) evt.getOldValue(); if (null != event && event.getArtifactType() == type) { @@ -418,10 +415,10 @@ public class ExtractedContent implements AutopsyVisitableItem { } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. Currently, - * remote events may be received for a case that is already - * closed. + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked + * out. Currently, remote events may be received for a case + * that is already closed. */ try { Case.getCurrentCase(); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java index 4b4659aa94..521a529eb7 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2014 Basis Technology Corp. + * Copyright 2013-2015 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -178,15 +178,15 @@ public class FileSize implements AutopsyVisitableItem { public void propertyChange(PropertyChangeEvent evt) { String eventType = evt.getPropertyName(); - // new file was added if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) { /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. - * Currently, remote events may be received for a case - * that is already closed. + * Checking for a current case is a stop gap measure + * until a different way of handling the closing of + * cases is worked out. Currently, remote events may be + * received for a case that is already closed. */ try { + // new file was added // @@@ could check the size here and only fire off updates if we know the file meets the min size criteria Case.getCurrentCase(); update(); @@ -199,10 +199,10 @@ public class FileSize implements AutopsyVisitableItem { || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. - * Currently, remote events may be received for a case - * that is already closed. + * Checking for a current case is a stop gap measure + * until a different way of handling the closing of + * cases is worked out. Currently, remote events may be + * received for a case that is already closed. */ try { Case.getCurrentCase(); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java index d230725410..23b1f40f12 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2014 Basis Technology Corp. + * Copyright 2011-2015 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -157,10 +157,10 @@ public class FileTypesNode extends DisplayableItemNode { || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. - * Currently, remote events may be received for a case - * that is already closed. + * Checking for a current case is a stop gap measure + * until a different way of handling the closing of + * cases is worked out. Currently, remote events may be + * received for a case that is already closed. */ try { Case.getCurrentCase(); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java index 928ba3c5f2..b6d4794dd1 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2014 Basis Technology Corp. + * Copyright 2011-2015 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -180,13 +180,13 @@ public class HashsetHits implements AutopsyVisitableItem { private final PropertyChangeListener pcl = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { - String eventType = evt.getPropertyName(); + String eventType = evt.getPropertyName(); if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) { /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. Currently, - * remote events may be received for a case that is already - * closed. + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked + * out. Currently, remote events may be received for a case + * that is already closed. */ try { Case.getCurrentCase(); @@ -207,10 +207,10 @@ public class HashsetHits implements AutopsyVisitableItem { } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. Currently, - * remote events may be received for a case that is already - * closed. + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked + * out. Currently, remote events may be received for a case + * that is already closed. */ try { Case.getCurrentCase(); @@ -220,8 +220,7 @@ public class HashsetHits implements AutopsyVisitableItem { * Case is closed, do nothing. */ } - } - else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { + } 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(); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java index 4a476231ad..c4c0080679 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2015 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -177,17 +177,18 @@ public class InterestingHits implements AutopsyVisitableItem { String eventType = evt.getPropertyName(); if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) { /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. Currently, - * remote events may be received for a case that is already - * closed. + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked + * out. Currently, remote events may be received for a case + * that is already closed. */ try { Case.getCurrentCase(); /** - * Due to some unresolved issues with how cases are - * closed, it is possible for the event to have a null - * oldValue if the event is a remote event. + * Even with the check above, it is still possible that + * the case will be closed in a different thread before + * this code executes. If that happens, it is possible + * for the event to have a null oldValue. */ ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue(); if (null != eventData && (eventData.getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT @@ -202,10 +203,10 @@ public class InterestingHits implements AutopsyVisitableItem { } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. Currently, - * remote events may be received for a case that is already - * closed. + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked + * out. Currently, remote events may be received for a case + * that is already closed. */ try { Case.getCurrentCase(); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java index 44c530251e..c4e01e12d2 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2014 Basis Technology Corp. + * Copyright 2011-2015 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -248,17 +248,18 @@ public class KeywordHits implements AutopsyVisitableItem { String eventType = evt.getPropertyName(); if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) { /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. Currently, - * remote events may be received for a case that is already - * closed. + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked + * out. Currently, remote events may be received for a case + * that is already closed. */ try { Case.getCurrentCase(); /** - * Due to some unresolved issues with how cases are - * closed, it is possible for the event to have a null - * oldValue if the event is a remote event. + * Even with the check above, it is still possible that + * the case will be closed in a different thread before + * this code executes. If that happens, it is possible + * for the event to have a null oldValue. */ ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue(); if (null != eventData && eventData.getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT) { @@ -272,10 +273,10 @@ public class KeywordHits implements AutopsyVisitableItem { } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. Currently, - * remote events may be received for a case that is already - * closed. + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked + * out. Currently, remote events may be received for a case + * that is already closed. */ try { Case.getCurrentCase(); @@ -285,8 +286,7 @@ public class KeywordHits implements AutopsyVisitableItem { * Case is closed, do nothing. */ } - } - else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { + } 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(); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Reports.java b/Core/src/org/sleuthkit/autopsy/datamodel/Reports.java index 83a2772bda..105e7cd052 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Reports.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Reports.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014 Basis Technology Corp. + * Copyright 2011-2015 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -99,10 +99,10 @@ public final class Reports implements AutopsyVisitableItem { String eventType = evt.getPropertyName(); if (eventType.equals(Case.Events.REPORT_ADDED.toString())) { /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. - * Currently, remote events may be received for a case - * that is already closed. + * Checking for a current case is a stop gap measure + * until a different way of handling the closing of + * cases is worked out. Currently, remote events may be + * received for a case that is already closed. */ try { Case.getCurrentCase(); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index 9894aa32fb..d57919afc2 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013 Basis Technology Corp. + * Copyright 2011-2015 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -121,19 +121,20 @@ public class Tags implements AutopsyVisitableItem { String eventType = evt.getPropertyName(); if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) { /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. Currently, - * remote events may be received for a case that is already - * closed. + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked + * out. Currently, remote events may be received for a case + * that is already closed. */ try { Case.getCurrentCase(); /** - * There are two things to note here. It is possible for - * the event to have a null oldValue if the event is a - * remote event and the case is closed after the above - * call, but before this code executes. Second, the use - * of deprecated artifact types here is explained by the + * There are two things to note here. * First, even with + * the check above, it is still possible that the case + * will be closed in a different thread before this code + * executes. If that happens, it is possible for the + * event to have a null oldValue. Second, the use of + * deprecated artifact types here is explained by the * fact that in an ideal world, the TagsManager would * fire tag-related events so that the tags tree would * refresh. But, we haven't had a chance to add that, so @@ -154,10 +155,10 @@ public class Tags implements AutopsyVisitableItem { } } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. Currently, - * remote events may be received for a case that is already - * closed. + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked + * out. Currently, remote events may be received for a case + * that is already closed. */ try { Case.getCurrentCase(); diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index bd07ac054b..121b59000b 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -34,7 +34,6 @@ import java.util.logging.Level; import java.util.prefs.PreferenceChangeEvent; import java.util.prefs.PreferenceChangeListener; import javax.swing.Action; -import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.tree.TreeSelectionModel; import org.openide.explorer.ExplorerManager; @@ -560,9 +559,10 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat } // if the image is added to the case else if (changed.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { /** - * This is a stop gap measure until a different way of handling the - * closing of cases is worked out. Currently, remote events may be - * received for a case that is already closed. + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked out. + * Currently, remote events may be received for a case that is + * already closed. */ try { Case.getCurrentCase(); @@ -585,9 +585,10 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat || changed.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) || changed.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) { /** - * This is a stop gap measure until a different way of handling the - * closing of cases is worked out. Currently, remote events may be - * received for a case that is already closed. + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked out. + * Currently, remote events may be received for a case that is + * already closed. */ try { Case.getCurrentCase(); diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchFilter.java b/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchFilter.java index 48b2e5d417..be8a799556 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchFilter.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchFilter.java @@ -254,10 +254,10 @@ class DateSearchFilter extends AbstractFileSearchFilter { case DATA_SOURCE_ADDED: case DATA_SOURCE_DELETED: /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. Currently, - * remote events may be received for a case that is already - * closed. + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked + * out. Currently, remote events may be received for a case + * that is already closed. */ try { Case.getCurrentCase(); diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index 80eec14f1d..cb055fcb98 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -362,7 +362,7 @@ public class IngestManager { * ingest message box, NetBeans progress handles, etc. Running interactively * is the default. */ - synchronized boolean isRunningInteractively() { + public synchronized boolean isRunningInteractively() { return this.runInteractively; } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java index b5fcd7dc61..bb92d57611 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java @@ -680,10 +680,23 @@ public class TimeLineController { public void propertyChange(PropertyChangeEvent evt) { switch (IngestManager.IngestModuleEvent.valueOf(evt.getPropertyName())) { case FILE_DONE: - Platform.runLater(() -> { - newEventsFlag.set(true); - }); - break; + /** + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked + * out. Currently, remote events may be received for a case + * that is already closed. + */ + try { + Case.getCurrentCase(); + Platform.runLater(() -> { + newEventsFlag.set(true); + }); + break; + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } } } } @@ -697,10 +710,10 @@ public class TimeLineController { case CANCELLED: case COMPLETED: /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. Currently, - * remote events may be received for a case that is already - * closed. + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked + * out. Currently, remote events may be received for a case + * that is already closed. */ try { Case.getCurrentCase(); @@ -725,10 +738,10 @@ public class TimeLineController { switch (Case.Events.valueOf(evt.getPropertyName())) { case DATA_SOURCE_ADDED: /** - * This is a stop gap measure until a different way of - * handling the closing of cases is worked out. Currently, - * remote events may be received for a case that is already - * closed. + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked + * out. Currently, remote events may be received for a case + * that is already closed. */ try { Case.getCurrentCase(); From ad376fc96df1bb9d87ccb43346712a37bcebc8ba Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Fri, 19 Jun 2015 14:28:10 -0400 Subject: [PATCH 3/3] Restrict events and UI if not running interactively --- .../sleuthkit/autopsy/casemodule/Case.java | 42 +++--- .../DirectoryTreeTopComponent.java | 138 +++++++++--------- .../autopsy/events/RemoteEventPublisher.java | 57 ++++---- .../netbeans/core/startup/Bundle.properties | 2 +- .../core/windows/view/ui/Bundle.properties | 2 +- 5 files changed, 125 insertions(+), 116 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 6dfa935f6e..4ec24c9f7e 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -1392,29 +1392,33 @@ public class Case { Case.clearTempFolder(); checkSubFolders(toChangeTo); - // enable these menus - CallableSystemAction.get(AddImageAction.class).setEnabled(true); - CallableSystemAction.get(CaseCloseAction.class).setEnabled(true); - CallableSystemAction.get(CasePropertiesAction.class).setEnabled(true); - CallableSystemAction.get(CaseDeleteAction.class).setEnabled(true); // Delete Case menu + if (IngestManager.getInstance().isRunningInteractively()) { + // enable these menus + CallableSystemAction.get(AddImageAction.class).setEnabled(true); + CallableSystemAction.get(CaseCloseAction.class).setEnabled(true); + CallableSystemAction.get(CasePropertiesAction.class).setEnabled(true); + CallableSystemAction.get(CaseDeleteAction.class).setEnabled(true); // Delete Case menu - if (toChangeTo.hasData()) { - // open all top components - CoreComponentControl.openCoreWindows(); - } else { - // close all top components - CoreComponentControl.closeCoreWindows(); + if (toChangeTo.hasData()) { + // open all top components + CoreComponentControl.openCoreWindows(); + } else { + // close all top components + CoreComponentControl.closeCoreWindows(); + } } } else { // case is closed - // close all top components first - CoreComponentControl.closeCoreWindows(); - - // disable these menus - CallableSystemAction.get(AddImageAction.class).setEnabled(false); // Add Image menu - CallableSystemAction.get(CaseCloseAction.class).setEnabled(false); // Case Close menu - CallableSystemAction.get(CasePropertiesAction.class).setEnabled(false); // Case Properties menu - CallableSystemAction.get(CaseDeleteAction.class).setEnabled(false); // Delete Case menu + if (IngestManager.getInstance().isRunningInteractively()) { + // close all top components first + CoreComponentControl.closeCoreWindows(); + // disable these menus + CallableSystemAction.get(AddImageAction.class).setEnabled(false); // Add Image menu + CallableSystemAction.get(CaseCloseAction.class).setEnabled(false); // Case Close menu + CallableSystemAction.get(CasePropertiesAction.class).setEnabled(false); // Case Properties menu + CallableSystemAction.get(CaseDeleteAction.class).setEnabled(false); // Delete Case menu + } + //clear pending notifications MessageNotifyUtil.Notify.clear(); diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index 121b59000b..1674f68a91 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -523,80 +523,82 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat */ @Override public void propertyChange(PropertyChangeEvent evt) { - String changed = evt.getPropertyName(); - if (changed.equals(Case.Events.CURRENT_CASE.toString())) { // changed current case - // When a case is closed, the old value of this property is the - // closed Case object and the new value is null. When a case is - // opened, the old value is null and the new value is the new Case - // object. - // @@@ This needs to be revisited. Perhaps case closed and case - // opened events instead of property change events would be a better - // solution. Either way, more probably needs to be done to clean up - // data model objects when a case is closed. - if (evt.getOldValue() != null && evt.getNewValue() == null) { - // The current case has been closed. Reset the ExplorerManager. - SwingUtilities.invokeLater(() -> { - Node emptyNode = new AbstractNode(Children.LEAF); - em.setRootContext(emptyNode); - }); - } else if (evt.getNewValue() != null) { - // A new case has been opened. Reset the ExplorerManager. - Case newCase = (Case) evt.getNewValue(); - final String newCaseName = newCase.getName(); - SwingUtilities.invokeLater(() -> { - em.getRootContext().setName(newCaseName); - em.getRootContext().setDisplayName(newCaseName); + if (IngestManager.getInstance().isRunningInteractively()) { + String changed = evt.getPropertyName(); + if (changed.equals(Case.Events.CURRENT_CASE.toString())) { // changed current case + // When a case is closed, the old value of this property is the + // closed Case object and the new value is null. When a case is + // opened, the old value is null and the new value is the new Case + // object. + // @@@ This needs to be revisited. Perhaps case closed and case + // opened events instead of property change events would be a better + // solution. Either way, more probably needs to be done to clean up + // data model objects when a case is closed. + if (evt.getOldValue() != null && evt.getNewValue() == null) { + // The current case has been closed. Reset the ExplorerManager. + SwingUtilities.invokeLater(() -> { + Node emptyNode = new AbstractNode(Children.LEAF); + em.setRootContext(emptyNode); + }); + } else if (evt.getNewValue() != null) { + // A new case has been opened. Reset the ExplorerManager. + Case newCase = (Case) evt.getNewValue(); + final String newCaseName = newCase.getName(); + SwingUtilities.invokeLater(() -> { + em.getRootContext().setName(newCaseName); + em.getRootContext().setDisplayName(newCaseName); // Reset the forward and back - // buttons. Note that a call to CoreComponentControl.openCoreWindows() - // by the new Case object will lead to a componentOpened() call - // that will repopulate the tree. - // @@@ The repopulation of the tree in this fashion also merits - // reconsideration. - resetHistory(); + // buttons. Note that a call to CoreComponentControl.openCoreWindows() + // by the new Case object will lead to a componentOpened() call + // that will repopulate the tree. + // @@@ The repopulation of the tree in this fashion also merits + // reconsideration. + resetHistory(); + }); + } + } // if the image is added to the case + else if (changed.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { + /** + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked out. + * Currently, remote events may be received for a case that is + * already closed. + */ + try { + Case.getCurrentCase(); + CoreComponentControl.openCoreWindows(); + SwingUtilities.invokeLater(this::componentOpened); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } + } // change in node selection + else if (changed.equals(ExplorerManager.PROP_SELECTED_NODES)) { + SwingUtilities.invokeLater(() -> { + respondSelection((Node[]) evt.getOldValue(), (Node[]) evt.getNewValue()); }); - } - } // if the image is added to the case - else if (changed.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { - /** - * Checking for a current case is a stop gap measure until a - * different way of handling the closing of cases is worked out. - * Currently, remote events may be received for a case that is - * already closed. - */ - try { - Case.getCurrentCase(); - CoreComponentControl.openCoreWindows(); - SwingUtilities.invokeLater(this::componentOpened); - } catch (IllegalStateException notUsed) { - /** - * Case is closed, do nothing. - */ - } - } // change in node selection - else if (changed.equals(ExplorerManager.PROP_SELECTED_NODES)) { - SwingUtilities.invokeLater(() -> { - respondSelection((Node[]) evt.getOldValue(), (Node[]) evt.getNewValue()); - }); - } else if (changed.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) { + } else if (changed.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) { // nothing to do here. - // all nodes should be listening for these events and update accordingly. - } else if (changed.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) - || changed.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) - || changed.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) { - /** - * Checking for a current case is a stop gap measure until a - * different way of handling the closing of cases is worked out. - * Currently, remote events may be received for a case that is - * already closed. - */ - try { - Case.getCurrentCase(); - SwingUtilities.invokeLater(this::refreshDataSourceTree); - } catch (IllegalStateException notUsed) { + // all nodes should be listening for these events and update accordingly. + } else if (changed.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) + || changed.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) + || changed.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) { /** - * Case is closed, do nothing. + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked out. + * Currently, remote events may be received for a case that is + * already closed. */ + try { + Case.getCurrentCase(); + SwingUtilities.invokeLater(this::refreshDataSourceTree); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } } } } diff --git a/Core/src/org/sleuthkit/autopsy/events/RemoteEventPublisher.java b/Core/src/org/sleuthkit/autopsy/events/RemoteEventPublisher.java index c4cf9248c7..85d4cc8f83 100644 --- a/Core/src/org/sleuthkit/autopsy/events/RemoteEventPublisher.java +++ b/Core/src/org/sleuthkit/autopsy/events/RemoteEventPublisher.java @@ -34,6 +34,7 @@ import javax.jms.Topic; import org.apache.activemq.ActiveMQConnectionFactory; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.ingest.IngestManager; /** * Provides thread-safe support for publishing events to registered subscribers @@ -135,38 +136,40 @@ final class RemoteEventPublisher { */ @Override public void onMessage(Message message) { - /** - * This is a stop gap measure until a different way of handling the - * closing of cases is worked out. Currently, Case.currentCase is - * set to null before Case.Event.CURRENT_CASE is published. That - * means that clients of this class have not had the chance to close - * their remote event channels and remote events may be received for - * a case that is already closed. - */ - try { - Case.getCurrentCase(); - } catch (IllegalStateException notUsed) { + if (IngestManager.getInstance().isRunningInteractively()) { /** - * Case is closed, do not publish the event. + * This is a stop gap measure until a different way of handling + * the closing of cases is worked out. Currently, + * Case.currentCase is set to null before + * Case.Event.CURRENT_CASE is published. That means that clients + * of this class have not had the chance to close their remote + * event channels and remote events may be received for a case + * that is already closed. */ - return; - } - - try { - if (message instanceof ObjectMessage) { - ObjectMessage objectMessage = (ObjectMessage) message; - Object object = objectMessage.getObject(); - if (object instanceof AutopsyEvent) { - AutopsyEvent event = (AutopsyEvent) object; - event.setSourceType(AutopsyEvent.SourceType.REMOTE); - localPublisher.publish(event); - } + try { + Case.getCurrentCase(); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do not publish the event. + */ + return; + } + + try { + if (message instanceof ObjectMessage) { + ObjectMessage objectMessage = (ObjectMessage) message; + Object object = objectMessage.getObject(); + if (object instanceof AutopsyEvent) { + AutopsyEvent event = (AutopsyEvent) object; + event.setSourceType(AutopsyEvent.SourceType.REMOTE); + localPublisher.publish(event); + } + } + } catch (Exception ex) { + logger.log(Level.SEVERE, "Error receiving message", ex); } - } catch (Exception ex) { - logger.log(Level.SEVERE, "Error receiving message", ex); } } - } } diff --git a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties index 0b319fa533..cd1d0cd2c8 100644 --- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Mon, 08 Jun 2015 11:37:44 -0400 +#Fri, 19 Jun 2015 13:59:39 -0400 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=314 SPLASH_WIDTH=538 diff --git a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties index 90c8ec5261..0639304dec 100644 --- a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties +++ b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Mon, 08 Jun 2015 11:37:44 -0400 +#Fri, 19 Jun 2015 13:59:39 -0400 CTL_MainWindow_Title=Autopsy 3.1.2 CTL_MainWindow_Title_No_Project=Autopsy 3.1.2