Merge branch 'sleuthkit:develop' into develop

This commit is contained in:
Seb2lyon 2021-06-17 17:58:04 +02:00 committed by GitHub
commit 05e50ce769
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 538 additions and 398 deletions

View File

@ -26,8 +26,10 @@ import java.util.Date;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionEvent;
import javax.swing.table.AbstractTableModel; import javax.swing.table.AbstractTableModel;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
@ -51,12 +53,13 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel {
private static final Set<IngestManager.IngestJobEvent> INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.STARTED, IngestManager.IngestJobEvent.CANCELLED, IngestManager.IngestJobEvent.COMPLETED); private static final Set<IngestManager.IngestJobEvent> INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.STARTED, IngestManager.IngestJobEvent.CANCELLED, IngestManager.IngestJobEvent.COMPLETED);
private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.CURRENT_CASE); private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.CURRENT_CASE);
private static final int EXTRA_ROW_HEIGHT = 4; private static final int EXTRA_ROW_HEIGHT = 4;
private List<IngestJobInfo> ingestJobs; private final List<IngestJobInfo> ingestJobs = new ArrayList<>();
private final List<IngestJobInfo> ingestJobsForSelectedDataSource = new ArrayList<>(); private final List<IngestJobInfo> ingestJobsForSelectedDataSource = new ArrayList<>();
private IngestJobTableModel ingestJobTableModel = new IngestJobTableModel(); private IngestJobTableModel ingestJobTableModel = new IngestJobTableModel();
private IngestModuleTableModel ingestModuleTableModel = new IngestModuleTableModel(null); private IngestModuleTableModel ingestModuleTableModel = new IngestModuleTableModel(null);
private final DateFormat datetimeFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); private final DateFormat datetimeFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
private DataSource selectedDataSource; private DataSource selectedDataSource;
private static SwingWorker<Boolean, Void> refreshWorker = null;
/** /**
* Creates new form IngestJobInfoPanel * Creates new form IngestJobInfoPanel
@ -133,27 +136,51 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel {
* Get the updated complete list of ingest jobs. * Get the updated complete list of ingest jobs.
*/ */
private void refresh() { private void refresh() {
if (refreshWorker != null && !refreshWorker.isDone()) {
refreshWorker.cancel(true);
}
refreshWorker = new SwingWorker<Boolean, Void>() {
@Override
protected Boolean doInBackground() throws Exception {
ingestJobs.clear();
try { try {
if (Case.isCaseOpen()) { // Note - this will generally return true when handling a case close event if (Case.isCaseOpen()) { // Note - this will generally return true when handling a case close event
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
this.ingestJobs = skCase.getIngestJobs(); ingestJobs.addAll(skCase.getIngestJobs());
setDataSource(selectedDataSource); setDataSource(selectedDataSource);
} else { } else {
this.ingestJobs = new ArrayList<>();
setDataSource(null); setDataSource(null);
} }
return true;
} catch (TskCoreException | NoCurrentCaseException ex) { } catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Failed to load ingest jobs.", ex); logger.log(Level.SEVERE, "Failed to load ingest jobs.", ex);
JOptionPane.showMessageDialog(this, Bundle.IngestJobInfoPanel_loadIngestJob_error_text(), Bundle.IngestJobInfoPanel_loadIngestJob_error_title(), JOptionPane.ERROR_MESSAGE); return false;
} }
} }
@Override
protected void done() {
try {
if (!get()) {
JOptionPane.showMessageDialog(IngestJobInfoPanel.this, Bundle.IngestJobInfoPanel_loadIngestJob_error_text(), Bundle.IngestJobInfoPanel_loadIngestJob_error_title(), JOptionPane.ERROR_MESSAGE);
}
} catch (InterruptedException | ExecutionException ex) {
logger.log(Level.WARNING, "Error getting results from Ingest Job Info Panel's refresh worker", ex);
}
}
};
refreshWorker.execute();
}
/** /**
* Reset the panel. * Reset the panel.
*/ */
private void reset() { private void reset() {
this.ingestJobs = new ArrayList<>(); if (refreshWorker != null) {
refreshWorker.cancel(true);
}
this.ingestJobs.clear();
setDataSource(null); setDataSource(null);
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2019 Basis Technology Corp. * Copyright 2019-2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -164,7 +164,9 @@ final class CallLogViewer extends javax.swing.JPanel implements RelationshipsVie
@Override @Override
public void setSelectionInfo(SelectionInfo info) { public void setSelectionInfo(SelectionInfo info) {
callLogDataViewer.setNode(null);
nodeFactory.refresh(info); nodeFactory.refresh(info);
} }
@Override @Override

View File

@ -36,6 +36,7 @@ import org.sleuthkit.datamodel.TskCoreException;
* ChildFactory for ContactNodes. * ChildFactory for ContactNodes.
*/ */
final class ContactsChildNodeFactory extends ChildFactory<BlackboardArtifact> { final class ContactsChildNodeFactory extends ChildFactory<BlackboardArtifact> {
private static final Logger logger = Logger.getLogger(ContactsChildNodeFactory.class.getName()); private static final Logger logger = Logger.getLogger(ContactsChildNodeFactory.class.getName());
private SelectionInfo selectionInfo; private SelectionInfo selectionInfo;
@ -51,7 +52,8 @@ final class ContactsChildNodeFactory extends ChildFactory<BlackboardArtifact>{
} }
/** /**
* Updates the current instance of selectionInfo and calls the refresh method. * Updates the current instance of selectionInfo and calls the refresh
* method.
* *
* @param selectionInfo New instance of the currently selected accounts * @param selectionInfo New instance of the currently selected accounts
*/ */
@ -63,7 +65,9 @@ final class ContactsChildNodeFactory extends ChildFactory<BlackboardArtifact>{
/** /**
* Creates a list of Keys (BlackboardArtifact) for only contacts of the * Creates a list of Keys (BlackboardArtifact) for only contacts of the
* currently selected accounts * currently selected accounts
*
* @param list List of BlackboardArtifact to populate * @param list List of BlackboardArtifact to populate
*
* @return True on success * @return True on success
*/ */
@Override @Override

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2019 Basis Technology Corp. * Copyright 2019-2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -35,7 +35,6 @@ import org.openide.nodes.NodeAdapter;
import org.openide.nodes.NodeMemberEvent; import org.openide.nodes.NodeMemberEvent;
import org.openide.util.Lookup; import org.openide.util.Lookup;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.communications.ModifiableProxyLookup; import org.sleuthkit.autopsy.communications.ModifiableProxyLookup;
import org.sleuthkit.autopsy.corecomponents.TableFilterNode; import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
import org.sleuthkit.autopsy.directorytree.DataResultFilterNode; import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
@ -126,6 +125,7 @@ final class ContactsViewer extends JPanel implements RelationshipsViewer {
@Override @Override
public void setSelectionInfo(SelectionInfo info) { public void setSelectionInfo(SelectionInfo info) {
contactPane.setNode(null);
nodeFactory.refresh(info); nodeFactory.refresh(info);
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2019 Basis Technology Corp. * Copyright 2019-2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -99,7 +99,8 @@ final class MediaViewer extends JPanel implements RelationshipsViewer, ExplorerM
public void setSelectionInfo(SelectionInfo info) { public void setSelectionInfo(SelectionInfo info) {
Set<Content> relationshipSources; Set<Content> relationshipSources;
Set<BlackboardArtifact> artifactList = new HashSet<>(); Set<BlackboardArtifact> artifactList = new HashSet<>();
contentViewer.setNode(null);
if (info != null) {
try { try {
relationshipSources = info.getRelationshipSources(); relationshipSources = info.getRelationshipSources();
@ -110,7 +111,7 @@ final class MediaViewer extends JPanel implements RelationshipsViewer, ExplorerM
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.WARNING, "Unable to update selection.", ex); logger.log(Level.WARNING, "Unable to update selection.", ex);
} }
}
thumbnailViewer.resetComponent(); thumbnailViewer.resetComponent();
thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(new AttachmentThumbnailsChildren(artifactList)), tableEM), true, this.getClass().getName())); thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(new AttachmentThumbnailsChildren(artifactList)), tableEM), true, this.getClass().getName()));

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2019 Basis Technology Corp. * Copyright 2019-2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -18,7 +18,6 @@
*/ */
package org.sleuthkit.autopsy.communications.relationships; package org.sleuthkit.autopsy.communications.relationships;
import java.awt.Component;
import javax.swing.JPanel; import javax.swing.JPanel;
import org.openide.util.Lookup; import org.openide.util.Lookup;
import org.sleuthkit.autopsy.communications.ModifiableProxyLookup; import org.sleuthkit.autopsy.communications.ModifiableProxyLookup;
@ -95,13 +94,11 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
private void tabPaneStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_tabPaneStateChanged private void tabPaneStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_tabPaneStateChanged
if(currentSelection != null) { RelationshipsViewer viewer = ((RelationshipsViewer) tabPane.getSelectedComponent());
((RelationshipsViewer) tabPane.getSelectedComponent()).setSelectionInfo(currentSelection); //clear old values
} viewer.setSelectionInfo(currentSelection);
if (viewer instanceof Lookup.Provider) {
Component selectedComponent = tabPane.getSelectedComponent(); Lookup lookup = viewer.getLookup();
if(selectedComponent instanceof Lookup.Provider) {
Lookup lookup = ((Lookup.Provider)selectedComponent).getLookup();
proxyLookup.setNewLookups(lookup); proxyLookup.setNewLookups(lookup);
} }
}//GEN-LAST:event_tabPaneStateChanged }//GEN-LAST:event_tabPaneStateChanged

View File

@ -97,30 +97,28 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
public void setArtifact(BlackboardArtifact artifact) { public void setArtifact(BlackboardArtifact artifact) {
resetComponent(); resetComponent();
if (artifact == null) {
return;
}
CallLogViewData callLogViewData = null; CallLogViewData callLogViewData = null;
try { try {
callLogViewData = getCallLogViewData(artifact); callLogViewData = getCallLogViewData(artifact);
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, String.format("Error getting attributes for Calllog artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex); logger.log(Level.SEVERE, String.format("Error getting attributes for Calllog artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex);
} }
List<AccountPersonaSearcherData> personaSearchDataList = new ArrayList<>();
// update the view with the call log data // update the view with the call log data
if (callLogViewData != null) { if (callLogViewData != null) {
List<AccountPersonaSearcherData> personaSearchDataList = updateView(callLogViewData); personaSearchDataList.addAll(updateView(callLogViewData));
}
if (!personaSearchDataList.isEmpty()) { if (!personaSearchDataList.isEmpty()) {
currentAccountFetcher = new PersonaAccountFetcher(artifact, personaSearchDataList, this); currentAccountFetcher = new PersonaAccountFetcher(artifact, personaSearchDataList, this);
currentAccountFetcher.execute(); currentAccountFetcher.execute();
} else { } else {
currentAccountFetcher = null; currentAccountFetcher = null;
} }
}
// repaint // repaint
this.revalidate(); this.revalidate();
this.repaint();
} }
/** /**
@ -371,8 +369,6 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
this.setLayout(m_gridBagLayout); this.setLayout(m_gridBagLayout);
this.revalidate(); this.revalidate();
this.repaint();
return dataList; return dataList;
} }

View File

@ -130,19 +130,15 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
// Reset the panel. // Reset the panel.
resetComponent(); resetComponent();
if (artifact == null) { if (artifact != null) {
return;
}
try { try {
extractArtifactData(artifact); extractArtifactData(artifact);
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, String.format("Error getting attributes for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex); logger.log(Level.SEVERE, String.format("Error getting attributes for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex);
return; return;
} }
updateView(); updateView();
}
this.setLayout(this.m_gridBagLayout); this.setLayout(this.m_gridBagLayout);
this.revalidate(); this.revalidate();
this.repaint(); this.repaint();
@ -164,6 +160,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
* Extracts data from the artifact to be displayed in the panel. * Extracts data from the artifact to be displayed in the panel.
* *
* @param artifact Artifact to show. * @param artifact Artifact to show.
*
* @throws TskCoreException * @throws TskCoreException
*/ */
private void extractArtifactData(BlackboardArtifact artifact) throws TskCoreException { private void extractArtifactData(BlackboardArtifact artifact) throws TskCoreException {

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2020 Basis Technology Corp. * Copyright 2011-2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -36,6 +36,7 @@ import org.openide.nodes.Node;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.Lookup; import org.openide.util.Lookup;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.WeakListeners;
import org.openide.util.lookup.Lookups; import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
@ -278,6 +279,8 @@ public class Artifacts {
private final RefreshThrottler refreshThrottler = new RefreshThrottler(this); private final RefreshThrottler refreshThrottler = new RefreshThrottler(this);
private final Category category; private final Category category;
private final PropertyChangeListener weakPcl;
/** /**
* Main constructor. * Main constructor.
* *
@ -290,9 +293,8 @@ public class Artifacts {
super(); super();
this.filteringDSObjId = filteringDSObjId; this.filteringDSObjId = filteringDSObjId;
this.category = category; this.category = category;
}
private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> { PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
String eventType = evt.getPropertyName(); String eventType = evt.getPropertyName();
if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { 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 // case was closed. Remove listeners so that we don't get called with a stale case handle
@ -302,9 +304,10 @@ public class Artifacts {
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
/** /**
* This is a stop gap measure until a different way of handling * This is a stop gap measure until a different way of
* the closing of cases is worked out. Currently, remote events * handling the closing of cases is worked out. Currently,
* may be received for a case that is already closed. * remote events may be received for a case that is already
* closed.
*/ */
try { try {
Case.getCurrentCaseThrows(); Case.getCurrentCaseThrows();
@ -317,18 +320,23 @@ public class Artifacts {
} }
}; };
@Override weakPcl = WeakListeners.propertyChange(pcl, null);
protected void addNotify() {
refreshThrottler.registerForIngestModuleEvents();
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
} }
@Override @Override
protected void removeNotify() { protected void addNotify() {
super.addNotify();
refreshThrottler.registerForIngestModuleEvents();
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
}
@Override
protected void finalize() throws Throwable {
super.finalize();
refreshThrottler.unregisterEventListener(); refreshThrottler.unregisterEventListener();
IngestManager.getInstance().removeIngestJobEventListener(pcl); IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
typeNodeMap.clear(); typeNodeMap.clear();
} }
@ -625,16 +633,20 @@ public class Artifacts {
} }
}; };
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
@Override @Override
protected void onAdd() { protected void onAdd() {
refreshThrottler.registerForIngestModuleEvents(); refreshThrottler.registerForIngestModuleEvents();
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
} }
@Override @Override
protected void onRemove() { protected void onRemove() {
if(refreshThrottler != null) {
refreshThrottler.unregisterEventListener(); refreshThrottler.unregisterEventListener();
IngestManager.getInstance().removeIngestJobEventListener(pcl); }
IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
} }
@Override @Override

View File

@ -1,6 +1,5 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
*
* Copyright 2018-2021 Basis Technology Corp. * Copyright 2018-2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
@ -20,7 +19,6 @@ package org.sleuthkit.autopsy.datamodel;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.EnumSet; import java.util.EnumSet;
@ -32,6 +30,7 @@ import java.util.stream.Collectors;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.openide.nodes.ChildFactory; import org.openide.nodes.ChildFactory;
import org.openide.nodes.Node; import org.openide.nodes.Node;
import org.openide.util.WeakListeners;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.CasePreferences; import org.sleuthkit.autopsy.casemodule.CasePreferences;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
@ -83,16 +82,18 @@ public final class AutopsyTreeChildFactory extends ChildFactory.Detachable<Objec
} }
}; };
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
@Override @Override
protected void addNotify() { protected void addNotify() {
super.addNotify(); super.addNotify();
Case.addEventTypeSubscriber(EVENTS_OF_INTEREST, pcl); Case.addEventTypeSubscriber(EVENTS_OF_INTEREST, weakPcl);
} }
@Override @Override
protected void removeNotify() { protected void finalize() throws Throwable {
super.removeNotify(); super.finalize();
Case.removeEventTypeSubscriber(EVENTS_OF_INTEREST, pcl); Case.removeEventTypeSubscriber(EVENTS_OF_INTEREST, weakPcl);
} }
/** /**
@ -128,7 +129,7 @@ public final class AutopsyTreeChildFactory extends ChildFactory.Detachable<Objec
.sorted() .sorted()
.collect(Collectors.toList()); .collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(personManager.getHostsForPerson(null))) { if (CollectionUtils.isNotEmpty(personManager.getHostsWithoutPersons())) {
nodes.add(new PersonGrouping(null)); nodes.add(new PersonGrouping(null));
} }
} else { } else {

View File

@ -122,7 +122,8 @@ public abstract class BaseChildFactory<T extends Content> extends ChildFactory.D
} }
@Override @Override
protected void removeNotify() { protected void finalize() throws Throwable {
super.finalize();
onRemove(); onRemove();
} }

View File

@ -31,6 +31,7 @@ import org.openide.nodes.Node;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.openide.util.WeakListeners;
import org.openide.util.lookup.Lookups; import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
@ -77,14 +78,17 @@ public class DataSourcesNode extends DisplayableItemNode {
} }
}; };
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
@Override @Override
protected void addNotify() { protected void addNotify() {
Case.addEventTypeSubscriber(UPDATE_EVTS, pcl); Case.addEventTypeSubscriber(UPDATE_EVTS, weakPcl);
} }
@Override @Override
protected void removeNotify() { protected void finalize() throws Throwable{
Case.removeEventTypeSubscriber(UPDATE_EVTS, pcl); Case.removeEventTypeSubscriber(UPDATE_EVTS, weakPcl);
super.finalize();
} }
@Override @Override

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2012-2020 Basis Technology Corp. * Copyright 2012-2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -37,6 +37,7 @@ import org.openide.nodes.Children;
import org.openide.nodes.Node; import org.openide.nodes.Node;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.WeakListeners;
import org.openide.util.lookup.Lookups; import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
@ -314,20 +315,23 @@ public class EmailExtracted implements AutopsyVisitableItem {
} }
}; };
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
@Override @Override
protected void addNotify() { protected void addNotify() {
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
emailResults.update(); emailResults.update();
emailResults.addObserver(this); emailResults.addObserver(this);
} }
@Override @Override
protected void removeNotify() { protected void finalize() throws Throwable{
IngestManager.getInstance().removeIngestJobEventListener(pcl); super.finalize();
IngestManager.getInstance().removeIngestModuleEventListener(pcl); IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
emailResults.deleteObserver(this); emailResults.deleteObserver(this);
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2020 Basis Technology Corp. * Copyright 2011-2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -39,6 +39,7 @@ import org.openide.nodes.Children;
import org.openide.nodes.Node; import org.openide.nodes.Node;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.WeakListeners;
import org.openide.util.lookup.Lookups; import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
@ -279,20 +280,23 @@ public class HashsetHits implements AutopsyVisitableItem {
} }
}; };
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
@Override @Override
protected void addNotify() { protected void addNotify() {
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
hashsetResults.update(); hashsetResults.update();
hashsetResults.addObserver(this); hashsetResults.addObserver(this);
} }
@Override @Override
protected void removeNotify() { protected void finalize() throws Throwable {
IngestManager.getInstance().removeIngestJobEventListener(pcl); super.finalize();
IngestManager.getInstance().removeIngestModuleEventListener(pcl); IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
hashsetResults.deleteObserver(this); hashsetResults.deleteObserver(this);
} }

View File

@ -94,14 +94,18 @@ public class HostNode extends DisplayableItemNode {
} }
}; };
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(dataSourceAddedPcl, null);
@Override @Override
protected void addNotify() { protected void addNotify() {
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.HOSTS_DELETED), dataSourceAddedPcl); super.addNotify();
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.HOSTS_DELETED), weakPcl);
} }
@Override @Override
protected void removeNotify() { protected void finalize() throws Throwable {
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.HOSTS_DELETED), dataSourceAddedPcl); super.finalize();
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.HOSTS_DELETED), weakPcl);
} }
@Override @Override

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2020 Basis Technology Corp. * Copyright 2011-2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -39,6 +39,7 @@ import org.openide.nodes.Children;
import org.openide.nodes.Node; import org.openide.nodes.Node;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.WeakListeners;
import org.openide.util.lookup.Lookups; import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
@ -272,20 +273,23 @@ public class InterestingHits implements AutopsyVisitableItem {
} }
}; };
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
@Override @Override
protected void addNotify() { protected void addNotify() {
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
interestingResults.update(); interestingResults.update();
interestingResults.addObserver(this); interestingResults.addObserver(this);
} }
@Override @Override
protected void removeNotify() { protected void finalize() throws Throwable {
IngestManager.getInstance().removeIngestJobEventListener(pcl); super.finalize();
IngestManager.getInstance().removeIngestModuleEventListener(pcl); IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
interestingResults.deleteObserver(this); interestingResults.deleteObserver(this);
} }

View File

@ -42,6 +42,7 @@ import org.openide.nodes.Node;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.Lookup; import org.openide.util.Lookup;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.WeakListeners;
import org.openide.util.lookup.Lookups; import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
@ -437,7 +438,8 @@ public class KeywordHits implements AutopsyVisitableItem {
} }
@Override @Override
protected void removeNotify() { protected void finalize() throws Throwable {
super.finalize();
keywordResults.deleteObserver(this); keywordResults.deleteObserver(this);
} }
@ -505,21 +507,23 @@ public class KeywordHits implements AutopsyVisitableItem {
} }
}; };
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
@Override @Override
protected void addNotify() { protected void addNotify() {
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
keywordResults.update(); keywordResults.update();
super.addNotify(); super.addNotify();
} }
@Override @Override
protected void removeNotify() { protected void finalize() throws Throwable{
IngestManager.getInstance().removeIngestJobEventListener(pcl); IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
IngestManager.getInstance().removeIngestModuleEventListener(pcl); IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
super.removeNotify(); super.finalize();
} }
@Override @Override

View File

@ -138,18 +138,21 @@ public final class OsAccounts implements AutopsyVisitableItem {
} }
}; };
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(listener, null);
@Override
protected void finalize() throws Throwable {
super.finalize();
Case.removeEventTypeSubscriber(Collections.singleton(Case.Events.OS_ACCOUNTS_ADDED), weakPcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
}
@Override @Override
protected void addNotify() { protected void addNotify() {
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.OS_ACCOUNTS_ADDED, Case.Events.OS_ACCOUNTS_DELETED), listener); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.OS_ACCOUNTS_ADDED, Case.Events.OS_ACCOUNTS_DELETED), listener);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), listener); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), listener);
} }
@Override
protected void removeNotify() {
Case.removeEventTypeSubscriber(Collections.singleton(Case.Events.OS_ACCOUNTS_ADDED), listener);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), listener);
}
@Override @Override
protected boolean createKeys(List<OsAccount> list) { protected boolean createKeys(List<OsAccount> list) {
if (skCase != null) { if (skCase != null) {

View File

@ -92,6 +92,7 @@ public class PersonNode extends DisplayableItemNode {
*/ */
PersonChildren(Person person) { PersonChildren(Person person) {
this.person = person; this.person = person;
} }
/** /**
@ -112,14 +113,17 @@ public class PersonNode extends DisplayableItemNode {
} }
}; };
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(hostAddedDeletedPcl, null);
@Override @Override
protected void addNotify() { protected void addNotify() {
Case.addEventTypeSubscriber(HOST_EVENTS_OF_INTEREST, hostAddedDeletedPcl); Case.addEventTypeSubscriber(HOST_EVENTS_OF_INTEREST, weakPcl);
} }
@Override @Override
protected void removeNotify() { protected void finalize() throws Throwable {
Case.removeEventTypeSubscriber(HOST_EVENTS_OF_INTEREST, hostAddedDeletedPcl); super.finalize();
Case.removeEventTypeSubscriber(HOST_EVENTS_OF_INTEREST, weakPcl);
} }
@Override @Override

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2019 Basis Technology Corp. * Copyright 2011-2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -33,6 +33,7 @@ import org.openide.nodes.Children;
import org.openide.nodes.Node; import org.openide.nodes.Node;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.WeakListeners;
import org.openide.util.lookup.Lookups; import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
@ -214,6 +215,8 @@ public class Tags implements AutopsyVisitableItem {
} }
}; };
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
/** /**
* Constructor * Constructor
* *
@ -221,21 +224,21 @@ public class Tags implements AutopsyVisitableItem {
*/ */
TagNameNodeFactory(long objId) { TagNameNodeFactory(long objId) {
this.filteringDSObjId = objId; this.filteringDSObjId = objId;
} }
@Override @Override
protected void addNotify() { protected void addNotify() {
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl); Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, weakPcl);
tagResults.update(); tagResults.update();
tagResults.addObserver(this); tagResults.addObserver(this);
} }
@Override @Override
protected void removeNotify() { protected void finalize() throws Throwable {
IngestManager.getInstance().removeIngestJobEventListener(pcl); super.finalize();
Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl); IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, weakPcl);
tagResults.deleteObserver(this); tagResults.deleteObserver(this);
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2019 Basis Technology Corp. * Copyright 2011-2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -57,6 +57,7 @@ import org.openide.nodes.NodeOp;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.Utilities; import org.openide.util.Utilities;
import org.openide.util.WeakListeners;
import org.openide.util.lookup.Lookups; import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
@ -218,8 +219,8 @@ final public class Accounts implements AutopsyVisitableItem {
abstract void handleDataAdded(ModuleDataEvent event); abstract void handleDataAdded(ModuleDataEvent event);
@Override @Override
protected void removeNotify() { protected void finalize() throws Throwable {
super.removeNotify(); super.finalize();
reviewStatusBus.unregister(ObservingChildren.this); reviewStatusBus.unregister(ObservingChildren.this);
} }
@ -416,6 +417,8 @@ final public class Accounts implements AutopsyVisitableItem {
} }
}; };
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
@Subscribe @Subscribe
@Override @Override
void handleReviewStatusChange(ReviewStatusChangeEvent event) { void handleReviewStatusChange(ReviewStatusChangeEvent event) {
@ -473,18 +476,18 @@ final public class Accounts implements AutopsyVisitableItem {
} }
@Override @Override
protected void removeNotify() { protected void finalize() throws Throwable {
IngestManager.getInstance().removeIngestJobEventListener(pcl); IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
IngestManager.getInstance().removeIngestModuleEventListener(pcl); IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
super.removeNotify(); super.finalize();
} }
@Override @Override
protected void addNotify() { protected void addNotify() {
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
super.addNotify(); super.addNotify();
refresh(true); refresh(true);
} }
@ -551,20 +554,21 @@ final public class Accounts implements AutopsyVisitableItem {
} }
}; };
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
@Override @Override
protected void addNotify() { protected void addNotify() {
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
super.addNotify();
} }
@Override @Override
protected void removeNotify() { protected void finalize() throws Throwable {
IngestManager.getInstance().removeIngestJobEventListener(pcl); super.finalize();
IngestManager.getInstance().removeIngestModuleEventListener(pcl); IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
super.removeNotify(); Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
} }
@Override @Override
@ -728,6 +732,9 @@ final public class Accounts implements AutopsyVisitableItem {
} }
}; };
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
@Subscribe @Subscribe
@Override @Override
void handleReviewStatusChange(ReviewStatusChangeEvent event) { void handleReviewStatusChange(ReviewStatusChangeEvent event) {
@ -742,17 +749,18 @@ final public class Accounts implements AutopsyVisitableItem {
@Override @Override
protected void addNotify() { protected void addNotify() {
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
super.addNotify(); super.addNotify();
} }
@Override @Override
protected void removeNotify() { protected void finalize() throws Throwable {
IngestManager.getInstance().removeIngestJobEventListener(pcl); super.finalize();
IngestManager.getInstance().removeIngestModuleEventListener(pcl); IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
super.removeNotify(); super.removeNotify();
} }
@ -882,20 +890,22 @@ final public class Accounts implements AutopsyVisitableItem {
} }
}; };
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
@Override @Override
protected void addNotify() { protected void addNotify() {
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
super.addNotify(); super.addNotify();
} }
@Override @Override
protected void removeNotify() { protected void finalize() throws Throwable {
IngestManager.getInstance().removeIngestJobEventListener(pcl); super.finalize();
IngestManager.getInstance().removeIngestModuleEventListener(pcl); IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
super.removeNotify(); Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
} }
@Subscribe @Subscribe
@ -1096,20 +1106,22 @@ final public class Accounts implements AutopsyVisitableItem {
} }
}; };
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
@Override @Override
protected void addNotify() { protected void addNotify() {
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
super.addNotify(); super.addNotify();
} }
@Override @Override
protected void removeNotify() { protected void finalize() throws Throwable{
IngestManager.getInstance().removeIngestJobEventListener(pcl); super.finalize();
IngestManager.getInstance().removeIngestModuleEventListener(pcl); IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
super.removeNotify(); Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
} }
@Subscribe @Subscribe

View File

@ -31,6 +31,7 @@ import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import org.apache.commons.lang3.StringUtils;
import org.openide.nodes.AbstractNode; import org.openide.nodes.AbstractNode;
import org.openide.explorer.ExplorerManager; import org.openide.explorer.ExplorerManager;
import org.openide.explorer.view.TreeView; import org.openide.explorer.view.TreeView;
@ -168,55 +169,127 @@ public class ViewContextAction extends AbstractAction {
public void actionPerformed(ActionEvent event) { public void actionPerformed(ActionEvent event) {
EventQueue.invokeLater(() -> { EventQueue.invokeLater(() -> {
/* Content parentContent = getParentContent(this.content);
* Get the parent content for the content to be selected in the
* results view. If the parent content is null, then the specified
* content is a data source, and the parent tree view node is the
* "Data Sources" node. Otherwise, the tree view needs to be
* searched to find the parent treeview node.
*/
Content parentContent = null;
try {
parentContent = content.getParent();
} catch (TskCoreException ex) {
MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindDirectory());
logger.log(Level.SEVERE, String.format("Could not get parent of Content object: %s", content), ex); //NON-NLS
return;
}
if ((parentContent != null) if ((parentContent != null) && (parentContent instanceof UnsupportedContent)) {
&& (parentContent instanceof UnsupportedContent)) {
MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_unsupportedParent()); MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_unsupportedParent());
logger.log(Level.WARNING, String.format("Could not navigate to unsupported content with id: %d", parentContent.getId())); //NON-NLS logger.log(Level.WARNING, String.format("Could not navigate to unsupported content with id: %d", parentContent.getId())); //NON-NLS
return; return;
} }
/* // Get the "Data Sources" node from the tree view.
* Get the "Data Sources" node from the tree view.
*/
DirectoryTreeTopComponent treeViewTopComponent = DirectoryTreeTopComponent.findInstance(); DirectoryTreeTopComponent treeViewTopComponent = DirectoryTreeTopComponent.findInstance();
ExplorerManager treeViewExplorerMgr = treeViewTopComponent.getExplorerManager(); ExplorerManager treeViewExplorerMgr = treeViewTopComponent.getExplorerManager();
Node parentTreeViewNode = null; Node parentTreeViewNode = null;
if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) { // 'Group by Data Source' view if (parentContent != null) {
if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) {
parentTreeViewNode = getParentNodeGroupedByPersonHost(treeViewExplorerMgr, parentContent);
} else {
parentTreeViewNode = getParentNodeGroupedByDataSource(treeViewExplorerMgr, parentContent);
}
}
// if no node is found, report error and do nothing
if (parentTreeViewNode == null) {
MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindNode());
logger.log(Level.SEVERE, "Failed to locate data source node in tree."); //NON-NLS
return;
}
setNodeSelection(this.content, parentTreeViewNode, treeViewTopComponent, treeViewExplorerMgr);
});
}
/**
* Get the parent content for the content to be selected in the results
* view. If the parent content is null, then the specified content is a data
* source, and the parent tree view node is the "Data Sources" node.
* Otherwise, the tree view needs to be searched to find the parent treeview
* node.
*
* @param content The content whose parent will be returned. If this item is
* a datasource, it will be returned.
*
* @return The content if content is a data source or the parent of this
* content.
*/
private Content getParentContent(Content content) {
try {
return (content instanceof DataSource)
? content
: content.getParent();
} catch (TskCoreException ex) {
MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindDirectory());
logger.log(Level.SEVERE, String.format("Could not get parent of Content object: %s", content), ex); //NON-NLS
return null;
}
}
/**
* Returns the node in the tree related to the parentContent or null if
* can't be found. This method should be used when view is grouped by data
* source.
*
* @param treeViewExplorerMgr The explorer manager.
* @param parentContent The content whose equivalent node will be
* returned if found.
*
* @return The node if found or null.
*/
private Node getParentNodeGroupedByDataSource(ExplorerManager treeViewExplorerMgr, Content parentContent) {
// Classic view
// Start the search at the DataSourcesNode
Children rootChildren = treeViewExplorerMgr.getRootContext().getChildren();
Node rootDsNode = rootChildren == null ? null : rootChildren.findChild(DataSourcesNode.getNameIdentifier());
if (rootDsNode != null) {
for (Node dataSourceLevelNode : getDataSourceLevelNodes(rootDsNode)) {
DataSource dataSource = dataSourceLevelNode.getLookup().lookup(DataSource.class);
if (dataSource != null) {
// the tree view needs to be searched to find the parent treeview node.
Node potentialParentTreeViewNode = findParentNodeInTree(parentContent, dataSourceLevelNode);
if (potentialParentTreeViewNode != null) {
return potentialParentTreeViewNode;
}
}
}
}
return null;
}
/**
* Returns the node in the tree related to the parentContent or null if
* can't be found. This method should be used when view is grouped by
* hosts/persons.
*
* @param treeViewExplorerMgr The explorer manager.
* @param parentContent The content whose equivalent node will be
* returned if found.
*
* @return The node if found or null.
*/
private Node getParentNodeGroupedByPersonHost(ExplorerManager treeViewExplorerMgr, Content parentContent) {
// 'Group by Data Source' view
SleuthkitCase skCase; SleuthkitCase skCase;
String dsname; String dsname;
try { try {
// get the objid/name of the datasource of the selected content. // get the objid/name of the datasource of the selected content.
skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
long contentDSObjid = content.getDataSource().getId(); long contentDSObjid = parentContent.getDataSource().getId();
DataSource datasource = skCase.getDataSource(contentDSObjid); DataSource datasource = skCase.getDataSource(contentDSObjid);
dsname = datasource.getName(); dsname = datasource.getName();
Children rootChildren = treeViewExplorerMgr.getRootContext().getChildren(); Children rootChildren = treeViewExplorerMgr.getRootContext().getChildren();
if (null != parentContent) {
// the tree view needs to be searched to find the parent treeview node. // the tree view needs to be searched to find the parent treeview node.
/* NOTE: we can't do a lookup by data source name here, becase if there /* NOTE: we can't do a lookup by data source name here, becase if there
are multiple data sources with the same name, then "getChildren().findChild(dsname)" are multiple data sources with the same name, then "getChildren().findChild(dsname)"
simply returns the first one that it finds. Instead we have to loop over all simply returns the first one that it finds. Instead we have to loop over all
data sources with that name, and make sure we find the correct one. data sources with that name, and make sure we find the correct one.
*/ */
List<Node> dataSourceLevelNodes = Stream.of(rootChildren.getNodes()) List<Node> dataSourceLevelNodes = Stream.of(rootChildren.getNodes(true))
.flatMap(rootNode -> getDataSourceLevelNodes(rootNode).stream()) .flatMap(rootNode -> getDataSourceLevelNodes(rootNode).stream())
.collect(Collectors.toList()); .collect(Collectors.toList());
@ -230,52 +303,28 @@ public class ViewContextAction extends AbstractAction {
Node datasourceGroupingNode = treeNode.getChildren().findChild(DataSourceFilesNode.getNameIdentifier()); Node datasourceGroupingNode = treeNode.getChildren().findChild(DataSourceFilesNode.getNameIdentifier());
// check whether this is the data source we are looking for // check whether this is the data source we are looking for
parentTreeViewNode = findParentNodeInTree(parentContent, datasourceGroupingNode); Node parentTreeViewNode = findParentNodeInTree(parentContent, datasourceGroupingNode);
if (parentTreeViewNode != null) { if (parentTreeViewNode != null) {
// found the data source node // found the data source node
break; return parentTreeViewNode;
} }
} }
} else {
/* If the parent content is null, then the specified
* content is a data source, and the parent tree view node is the
* "Data Sources" node. */
Node datasourceGroupingNode = rootChildren.findChild(dsname);
if (!Objects.isNull(datasourceGroupingNode)) {
Children dsChildren = datasourceGroupingNode.getChildren();
parentTreeViewNode = dsChildren.findChild(DataSourceFilesNode.getNameIdentifier());
}
}
if (parentTreeViewNode == null) {
MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindNode());
logger.log(Level.SEVERE, "Failed to locate data source node in tree."); //NON-NLS
return;
}
} catch (NoCurrentCaseException | TskDataException | TskCoreException ex) { } catch (NoCurrentCaseException | TskDataException | TskCoreException ex) {
MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindNode()); MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindNode());
logger.log(Level.SEVERE, "Failed to locate data source node in tree.", ex); //NON-NLS logger.log(Level.SEVERE, "Failed to locate data source node in tree.", ex); //NON-NLS
return;
}
} else { // Classic view
// Start the search at the DataSourcesNode
Children rootChildren = treeViewExplorerMgr.getRootContext().getChildren();
Node rootDsNode = rootChildren == null ? null : rootChildren.findChild(DataSourcesNode.getNameIdentifier());
if (rootDsNode != null) {
for (Node dataSourceLevelNode : getDataSourceLevelNodes(rootDsNode)) {
DataSource dataSource = dataSourceLevelNode.getLookup().lookup(DataSource.class);
if (dataSource != null) {
// the tree view needs to be searched to find the parent treeview node.
Node potentialParentTreeViewNode = findParentNodeInTree(parentContent, dataSourceLevelNode);
if (potentialParentTreeViewNode != null) {
parentTreeViewNode = potentialParentTreeViewNode;
break;
}
}
}
}
} }
return null;
}
/**
* Set the node selection in the tree.
* @param content The content to select.
* @param parentTreeViewNode The node that is the parent of the content.
* @param treeViewTopComponent The DirectoryTreeTopComponent.
* @param treeViewExplorerMgr The ExplorerManager.
*/
private void setNodeSelection(Content content, Node parentTreeViewNode, DirectoryTreeTopComponent treeViewTopComponent, ExplorerManager treeViewExplorerMgr) {
/* /*
* Set the child selection info of the parent tree node, then select * Set the child selection info of the parent tree node, then select
* the parent node in the tree view. The results view will retrieve * the parent node in the tree view. The results view will retrieve
@ -314,7 +363,6 @@ public class ViewContextAction extends AbstractAction {
logger.log(Level.SEVERE, "Failed to select the parent node in the tree view", ex); //NON-NLS logger.log(Level.SEVERE, "Failed to select the parent node in the tree view", ex); //NON-NLS
} }
} }
});
} }
/** /**
@ -322,22 +370,23 @@ public class ViewContextAction extends AbstractAction {
* returns itself. * returns itself.
* *
* @param node The node. * @param node The node.
*
* @return The child nodes that are at the data source level. * @return The child nodes that are at the data source level.
*/ */
private List<Node> getDataSourceLevelNodes(Node node) { private List<Node> getDataSourceLevelNodes(Node node) {
if (node == null) { if (node == null) {
return Collections.emptyList(); return Collections.emptyList();
} else if (node.getLookup().lookup(Host.class) != null || } else if (node.getLookup().lookup(Host.class) != null
node.getLookup().lookup(Person.class) != null || || node.getLookup().lookup(Person.class) != null
DataSourcesNode.getNameIdentifier().equals(node.getLookup().lookup(String.class)) || || DataSourcesNode.getNameIdentifier().equals(node.getLookup().lookup(String.class))
PersonNode.getUnknownPersonId().equals(node.getLookup().lookup(String.class))) { || PersonNode.getUnknownPersonId().equals(node.getLookup().lookup(String.class))) {
Children children = node.getChildren(); Children children = node.getChildren();
Node[] childNodes = children == null ? null : children.getNodes(); Node[] childNodes = children == null ? null : children.getNodes(true);
if (childNodes == null) { if (childNodes == null) {
return Collections.emptyList(); return Collections.emptyList();
} }
return Stream.of(node.getChildren().getNodes()) return Stream.of(node.getChildren().getNodes(true))
.flatMap(parent -> getDataSourceLevelNodes(parent).stream()) .flatMap(parent -> getDataSourceLevelNodes(parent).stream())
.collect(Collectors.toList()); .collect(Collectors.toList());
} else { } else {
@ -351,6 +400,7 @@ public class ViewContextAction extends AbstractAction {
* *
* @param parentContent parent content for the content to be searched for * @param parentContent parent content for the content to be searched for
* @param node Node tree to search * @param node Node tree to search
*
* @return Node object of the matching parent, NULL if not found * @return Node object of the matching parent, NULL if not found
*/ */
private Node findParentNodeInTree(Content parentContent, Node node) { private Node findParentNodeInTree(Content parentContent, Node node) {
@ -377,6 +427,11 @@ public class ViewContextAction extends AbstractAction {
Node dummyRootNode = new DirectoryTreeFilterNode(new AbstractNode(new RootContentChildren(contentBranch)), true); Node dummyRootNode = new DirectoryTreeFilterNode(new AbstractNode(new RootContentChildren(contentBranch)), true);
Children ancestorChildren = dummyRootNode.getChildren(); Children ancestorChildren = dummyRootNode.getChildren();
// if content is the data source provided, return that.
if (ancestorChildren.getNodesCount() == 1 && StringUtils.equals(ancestorChildren.getNodeAt(0).getName(), node.getName())) {
return node;
}
/* /*
* Search the tree for the parent node. Note that this algorithm * Search the tree for the parent node. Note that this algorithm
* simply discards "extra" ancestor nodes not shown in the tree, * simply discards "extra" ancestor nodes not shown in the tree,
@ -387,8 +442,9 @@ public class ViewContextAction extends AbstractAction {
Node parentTreeViewNode = null; Node parentTreeViewNode = null;
for (int i = 0; i < ancestorChildren.getNodesCount(); i++) { for (int i = 0; i < ancestorChildren.getNodesCount(); i++) {
Node ancestorNode = ancestorChildren.getNodeAt(i); Node ancestorNode = ancestorChildren.getNodeAt(i);
for (int j = 0; j < treeNodeChildren.getNodesCount(); j++) { Node[] treeNodeChilds = treeNodeChildren.getNodes(true);
Node treeNode = treeNodeChildren.getNodeAt(j); for (int j = 0; j < treeNodeChilds.length; j++) {
Node treeNode = treeNodeChilds[j];
if (ancestorNode.getName().equals(treeNode.getName())) { if (ancestorNode.getName().equals(treeNode.getName())) {
parentTreeViewNode = treeNode; parentTreeViewNode = treeNode;
treeNodeChildren = treeNode.getChildren(); treeNodeChildren = treeNode.getChildren();