mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 18:17:43 +00:00
Merge branch 'sleuthkit:develop' into develop
This commit is contained in:
commit
05e50ce769
@ -26,8 +26,10 @@ import java.util.Date;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.SwingWorker;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
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<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.CURRENT_CASE);
|
||||
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 IngestJobTableModel ingestJobTableModel = new IngestJobTableModel();
|
||||
private IngestModuleTableModel ingestModuleTableModel = new IngestModuleTableModel(null);
|
||||
private final DateFormat datetimeFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
|
||||
private DataSource selectedDataSource;
|
||||
private static SwingWorker<Boolean, Void> refreshWorker = null;
|
||||
|
||||
/**
|
||||
* Creates new form IngestJobInfoPanel
|
||||
@ -76,19 +79,19 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel {
|
||||
this.ingestModuleTable.setModel(this.ingestModuleTableModel);
|
||||
});
|
||||
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST , (PropertyChangeEvent evt) -> {
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, (PropertyChangeEvent evt) -> {
|
||||
if (evt.getPropertyName().equals(IngestManager.IngestJobEvent.STARTED.toString())
|
||||
|| evt.getPropertyName().equals(IngestManager.IngestJobEvent.CANCELLED.toString())
|
||||
|| evt.getPropertyName().equals(IngestManager.IngestJobEvent.COMPLETED.toString())) {
|
||||
refresh();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, (PropertyChangeEvent evt) -> {
|
||||
if (!(evt instanceof AutopsyEvent) || (((AutopsyEvent) evt).getSourceType() != AutopsyEvent.SourceType.LOCAL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Check whether we have a case open or case close event.
|
||||
if ((CURRENT_CASE == Case.Events.valueOf(evt.getPropertyName()))) {
|
||||
if (evt.getNewValue() != null) {
|
||||
@ -102,7 +105,7 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel {
|
||||
});
|
||||
ingestJobTable.setRowHeight(ingestJobTable.getRowHeight() + EXTRA_ROW_HEIGHT);
|
||||
ingestModuleTable.setRowHeight(ingestModuleTable.getRowHeight() + EXTRA_ROW_HEIGHT);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -133,27 +136,51 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel {
|
||||
* Get the updated complete list of ingest jobs.
|
||||
*/
|
||||
private void refresh() {
|
||||
try {
|
||||
if (Case.isCaseOpen()) { // Note - this will generally return true when handling a case close event
|
||||
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
|
||||
this.ingestJobs = skCase.getIngestJobs();
|
||||
setDataSource(selectedDataSource);
|
||||
} else {
|
||||
this.ingestJobs = new ArrayList<>();
|
||||
setDataSource(null);
|
||||
}
|
||||
|
||||
} catch (TskCoreException | NoCurrentCaseException 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);
|
||||
if (refreshWorker != null && !refreshWorker.isDone()) {
|
||||
refreshWorker.cancel(true);
|
||||
}
|
||||
refreshWorker = new SwingWorker<Boolean, Void>() {
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground() throws Exception {
|
||||
ingestJobs.clear();
|
||||
try {
|
||||
if (Case.isCaseOpen()) { // Note - this will generally return true when handling a case close event
|
||||
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
|
||||
ingestJobs.addAll(skCase.getIngestJobs());
|
||||
setDataSource(selectedDataSource);
|
||||
} else {
|
||||
setDataSource(null);
|
||||
}
|
||||
return true;
|
||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to load ingest jobs.", ex);
|
||||
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.
|
||||
*/
|
||||
private void reset() {
|
||||
this.ingestJobs = new ArrayList<>();
|
||||
if (refreshWorker != null) {
|
||||
refreshWorker.cancel(true);
|
||||
}
|
||||
this.ingestJobs.clear();
|
||||
setDataSource(null);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Copyright 2019-2021 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -119,9 +119,9 @@ final class CallLogViewer extends javax.swing.JPanel implements RelationshipsVie
|
||||
updateOutlineViewPanel();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
TableColumn column = outline.getColumnModel().getColumn(2);
|
||||
column.setCellRenderer(new NodeTableCellRenderer() );
|
||||
column.setCellRenderer(new NodeTableCellRenderer());
|
||||
|
||||
}
|
||||
|
||||
@ -164,7 +164,9 @@ final class CallLogViewer extends javax.swing.JPanel implements RelationshipsVie
|
||||
|
||||
@Override
|
||||
public void setSelectionInfo(SelectionInfo info) {
|
||||
callLogDataViewer.setNode(null);
|
||||
nodeFactory.refresh(info);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -229,7 +231,7 @@ final class CallLogViewer extends javax.swing.JPanel implements RelationshipsVie
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JScrollPane bottomScrollPane;
|
||||
private org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel outlineViewPanel;
|
||||
|
@ -35,7 +35,8 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
/**
|
||||
* 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 SelectionInfo selectionInfo;
|
||||
@ -47,12 +48,13 @@ final class ContactsChildNodeFactory extends ChildFactory<BlackboardArtifact>{
|
||||
* accounts
|
||||
*/
|
||||
ContactsChildNodeFactory(SelectionInfo selectionInfo) {
|
||||
this.selectionInfo = selectionInfo;
|
||||
this.selectionInfo = selectionInfo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public void refresh(SelectionInfo selectionInfo) {
|
||||
@ -63,13 +65,15 @@ final class ContactsChildNodeFactory extends ChildFactory<BlackboardArtifact>{
|
||||
/**
|
||||
* Creates a list of Keys (BlackboardArtifact) for only contacts of the
|
||||
* currently selected accounts
|
||||
*
|
||||
* @param list List of BlackboardArtifact to populate
|
||||
*
|
||||
* @return True on success
|
||||
*/
|
||||
@Override
|
||||
protected boolean createKeys(List<BlackboardArtifact> list) {
|
||||
|
||||
if(selectionInfo == null) {
|
||||
|
||||
if (selectionInfo == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -80,7 +84,7 @@ final class ContactsChildNodeFactory extends ChildFactory<BlackboardArtifact>{
|
||||
logger.log(Level.SEVERE, "Failed to load relationship sources.", ex); //NON-NLS
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> {
|
||||
|
||||
BlackboardArtifact bba = (BlackboardArtifact) content;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Copyright 2019-2021 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.communications.ModifiableProxyLookup;
|
||||
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
|
||||
import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
|
||||
@ -126,6 +125,7 @@ final class ContactsViewer extends JPanel implements RelationshipsViewer {
|
||||
|
||||
@Override
|
||||
public void setSelectionInfo(SelectionInfo info) {
|
||||
contactPane.setNode(null);
|
||||
nodeFactory.refresh(info);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Copyright 2019-2021 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -99,18 +99,19 @@ final class MediaViewer extends JPanel implements RelationshipsViewer, ExplorerM
|
||||
public void setSelectionInfo(SelectionInfo info) {
|
||||
Set<Content> relationshipSources;
|
||||
Set<BlackboardArtifact> artifactList = new HashSet<>();
|
||||
contentViewer.setNode(null);
|
||||
if (info != null) {
|
||||
try {
|
||||
relationshipSources = info.getRelationshipSources();
|
||||
|
||||
try {
|
||||
relationshipSources = info.getRelationshipSources();
|
||||
relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> {
|
||||
artifactList.add((BlackboardArtifact) content);
|
||||
});
|
||||
|
||||
relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> {
|
||||
artifactList.add((BlackboardArtifact) content);
|
||||
});
|
||||
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Unable to update selection.", ex);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Unable to update selection.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
thumbnailViewer.resetComponent();
|
||||
|
||||
thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(new AttachmentThumbnailsChildren(artifactList)), tableEM), true, this.getClass().getName()));
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Copyright 2019-2021 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,7 +18,6 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.communications.relationships;
|
||||
|
||||
import java.awt.Component;
|
||||
import javax.swing.JPanel;
|
||||
import org.openide.util.Lookup;
|
||||
import org.sleuthkit.autopsy.communications.ModifiableProxyLookup;
|
||||
@ -37,15 +36,15 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider
|
||||
*/
|
||||
public RelationshipBrowser() {
|
||||
initComponents();
|
||||
|
||||
|
||||
MessageViewer messagesViewer = new MessageViewer();
|
||||
ContactsViewer contactsViewer = new ContactsViewer();
|
||||
SummaryViewer summaryViewer = new SummaryViewer();
|
||||
MediaViewer mediaViewer = new MediaViewer();
|
||||
CallLogViewer callLogViewer = new CallLogViewer();
|
||||
|
||||
|
||||
proxyLookup = new ModifiableProxyLookup(messagesViewer.getLookup());
|
||||
|
||||
|
||||
tabPane.add(summaryViewer.getDisplayName(), summaryViewer);
|
||||
tabPane.add(messagesViewer.getDisplayName(), messagesViewer);
|
||||
tabPane.add(callLogViewer.getDisplayName(), callLogViewer);
|
||||
@ -95,13 +94,11 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void tabPaneStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_tabPaneStateChanged
|
||||
if(currentSelection != null) {
|
||||
((RelationshipsViewer) tabPane.getSelectedComponent()).setSelectionInfo(currentSelection);
|
||||
}
|
||||
|
||||
Component selectedComponent = tabPane.getSelectedComponent();
|
||||
if(selectedComponent instanceof Lookup.Provider) {
|
||||
Lookup lookup = ((Lookup.Provider)selectedComponent).getLookup();
|
||||
RelationshipsViewer viewer = ((RelationshipsViewer) tabPane.getSelectedComponent());
|
||||
//clear old values
|
||||
viewer.setSelectionInfo(currentSelection);
|
||||
if (viewer instanceof Lookup.Provider) {
|
||||
Lookup lookup = viewer.getLookup();
|
||||
proxyLookup.setNewLookups(lookup);
|
||||
}
|
||||
}//GEN-LAST:event_tabPaneStateChanged
|
||||
|
@ -97,30 +97,28 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
public void setArtifact(BlackboardArtifact artifact) {
|
||||
resetComponent();
|
||||
|
||||
if (artifact == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
CallLogViewData callLogViewData = null;
|
||||
try {
|
||||
callLogViewData = getCallLogViewData(artifact);
|
||||
} 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);
|
||||
}
|
||||
|
||||
List<AccountPersonaSearcherData> personaSearchDataList = new ArrayList<>();
|
||||
// update the view with the call log data
|
||||
if (callLogViewData != null) {
|
||||
List<AccountPersonaSearcherData> personaSearchDataList = updateView(callLogViewData);
|
||||
if (!personaSearchDataList.isEmpty()) {
|
||||
currentAccountFetcher = new PersonaAccountFetcher(artifact, personaSearchDataList, this);
|
||||
currentAccountFetcher.execute();
|
||||
} else {
|
||||
currentAccountFetcher = null;
|
||||
}
|
||||
personaSearchDataList.addAll(updateView(callLogViewData));
|
||||
|
||||
}
|
||||
if (!personaSearchDataList.isEmpty()) {
|
||||
currentAccountFetcher = new PersonaAccountFetcher(artifact, personaSearchDataList, this);
|
||||
currentAccountFetcher.execute();
|
||||
} else {
|
||||
currentAccountFetcher = null;
|
||||
}
|
||||
|
||||
// repaint
|
||||
this.revalidate();
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -320,7 +318,7 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
// Display "From" if we have non-local device accounts
|
||||
if (callLogViewData.getFromAccount() != null) {
|
||||
CommunicationArtifactViewerHelper.addKey(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_label_from());
|
||||
|
||||
|
||||
// check if this is local account
|
||||
String accountDisplayString = getAccountDisplayString(callLogViewData.getFromAccount(), callLogViewData);
|
||||
CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, this.m_constraints, accountDisplayString);
|
||||
@ -371,8 +369,6 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
|
||||
this.setLayout(m_gridBagLayout);
|
||||
this.revalidate();
|
||||
this.repaint();
|
||||
|
||||
return dataList;
|
||||
}
|
||||
|
||||
|
@ -130,19 +130,15 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
// Reset the panel.
|
||||
resetComponent();
|
||||
|
||||
if (artifact == null) {
|
||||
return;
|
||||
if (artifact != null) {
|
||||
try {
|
||||
extractArtifactData(artifact);
|
||||
} 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);
|
||||
return;
|
||||
}
|
||||
updateView();
|
||||
}
|
||||
|
||||
try {
|
||||
extractArtifactData(artifact);
|
||||
} 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);
|
||||
return;
|
||||
}
|
||||
|
||||
updateView();
|
||||
|
||||
this.setLayout(this.m_gridBagLayout);
|
||||
this.revalidate();
|
||||
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.
|
||||
*
|
||||
* @param artifact Artifact to show.
|
||||
*
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
private void extractArtifactData(BlackboardArtifact artifact) throws TskCoreException {
|
||||
@ -235,7 +232,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
/**
|
||||
* Updates the contact image in the view.
|
||||
*
|
||||
* @param contactPanelLayout Panel layout.
|
||||
* @param contactPanelLayout Panel layout.
|
||||
* @param contactPanelConstraints Layout constraints.
|
||||
*
|
||||
*/
|
||||
@ -267,7 +264,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
/**
|
||||
* Updates the contact name in the view.
|
||||
*
|
||||
* @param contactPanelLayout Panel layout.
|
||||
* @param contactPanelLayout Panel layout.
|
||||
* @param contactPanelConstraints Layout constraints.
|
||||
*
|
||||
*/
|
||||
@ -294,9 +291,9 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
* Updates the view by displaying the given list of attributes in the given
|
||||
* section panel.
|
||||
*
|
||||
* @param sectionAttributesList List of attributes to display.
|
||||
* @param sectionHeader Section name label.
|
||||
* @param contactPanelLayout Panel layout.
|
||||
* @param sectionAttributesList List of attributes to display.
|
||||
* @param sectionHeader Section name label.
|
||||
* @param contactPanelLayout Panel layout.
|
||||
* @param contactPanelConstraints Layout constraints.
|
||||
*
|
||||
*/
|
||||
@ -418,12 +415,12 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
/**
|
||||
* Displays the given persona in the persona panel.
|
||||
*
|
||||
* @param persona Persona to display.
|
||||
* @param matchNumber Number of matches.
|
||||
* @param persona Persona to display.
|
||||
* @param matchNumber Number of matches.
|
||||
* @param missingAccountsList List of contact accounts this persona may be
|
||||
* missing.
|
||||
* @param gridBagLayout Layout to use.
|
||||
* @param constraints layout constraints.
|
||||
* missing.
|
||||
* @param gridBagLayout Layout to use.
|
||||
* @param constraints layout constraints.
|
||||
*
|
||||
* @throws CentralRepoException
|
||||
*/
|
||||
@ -567,7 +564,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
* @param artifact
|
||||
*
|
||||
* @return Image from a TSK_CONTACT artifact or default image if none was
|
||||
* found or the artifact is not a TSK_CONTACT
|
||||
* found or the artifact is not a TSK_CONTACT
|
||||
*/
|
||||
private ImageIcon getImageFromArtifact(BlackboardArtifact artifact) {
|
||||
ImageIcon imageIcon = defaultImage;
|
||||
@ -617,7 +614,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
* Creates a persona searcher task.
|
||||
*
|
||||
* @param accountAttributesList List of attributes that may map to
|
||||
* accounts.
|
||||
* accounts.
|
||||
*/
|
||||
ContactPersonaSearcherTask(BlackboardArtifact artifact) {
|
||||
this.artifact = artifact;
|
||||
@ -647,7 +644,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Collection<PersonaAccount> personaAccounts = PersonaAccount.getPersonaAccountsForAccount(account);
|
||||
if (personaAccounts != null && !personaAccounts.isEmpty()) {
|
||||
// get personas for the account
|
||||
@ -716,7 +713,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param personaNameLabel Persona name label.
|
||||
* @param personaNameLabel Persona name label.
|
||||
* @param personaActionButton Persona action button.
|
||||
*/
|
||||
PersonaUIComponents(JLabel personaNameLabel, JButton personaActionButton) {
|
||||
@ -784,8 +781,8 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
for (CentralRepoAccount account : contactUniqueAccountsList) {
|
||||
personaPanel.addAccount(account, Bundle.ContactArtifactViewer_persona_account_justification(), Persona.Confidence.HIGH);
|
||||
}
|
||||
|
||||
if(contactName != null && contactUniqueAccountsList.isEmpty()) {
|
||||
|
||||
if (contactName != null && contactUniqueAccountsList.isEmpty()) {
|
||||
createPersonaDialog.setStartupPopupMessage(Bundle.ContactArtifactViewer_id_not_found_in_cr(contactName));
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2020 Basis Technology Corp.
|
||||
* Copyright 2011-2021 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.WeakListeners;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
@ -277,6 +278,8 @@ public class Artifacts {
|
||||
*/
|
||||
private final RefreshThrottler refreshThrottler = new RefreshThrottler(this);
|
||||
private final Category category;
|
||||
|
||||
private final PropertyChangeListener weakPcl;
|
||||
|
||||
/**
|
||||
* Main constructor.
|
||||
@ -290,45 +293,50 @@ public class Artifacts {
|
||||
super();
|
||||
this.filteringDSObjId = filteringDSObjId;
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
|
||||
String eventType = evt.getPropertyName();
|
||||
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();
|
||||
}
|
||||
} 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.getCurrentCaseThrows();
|
||||
refresh(false);
|
||||
} catch (NoCurrentCaseException notUsed) {
|
||||
|
||||
PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
|
||||
String eventType = evt.getPropertyName();
|
||||
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();
|
||||
}
|
||||
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
||||
/**
|
||||
* Case is closed, do nothing.
|
||||
* 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.getCurrentCaseThrows();
|
||||
refresh(false);
|
||||
} catch (NoCurrentCaseException notUsed) {
|
||||
/**
|
||||
* Case is closed, do nothing.
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
weakPcl = WeakListeners.propertyChange(pcl, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
protected void addNotify() {
|
||||
super.addNotify();
|
||||
refreshThrottler.registerForIngestModuleEvents();
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
refreshThrottler.unregisterEventListener();
|
||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
typeNodeMap.clear();
|
||||
}
|
||||
|
||||
@ -624,17 +632,21 @@ public class Artifacts {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
|
||||
|
||||
@Override
|
||||
protected void onAdd() {
|
||||
refreshThrottler.registerForIngestModuleEvents();
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl);
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRemove() {
|
||||
refreshThrottler.unregisterEventListener();
|
||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||
if(refreshThrottler != null) {
|
||||
refreshThrottler.unregisterEventListener();
|
||||
}
|
||||
IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2018-2021 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
@ -20,7 +19,6 @@ package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
@ -32,6 +30,7 @@ import java.util.stream.Collectors;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.util.WeakListeners;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.CasePreferences;
|
||||
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
|
||||
protected void addNotify() {
|
||||
super.addNotify();
|
||||
Case.addEventTypeSubscriber(EVENTS_OF_INTEREST, pcl);
|
||||
Case.addEventTypeSubscriber(EVENTS_OF_INTEREST, weakPcl);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
super.removeNotify();
|
||||
Case.removeEventTypeSubscriber(EVENTS_OF_INTEREST, pcl);
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
Case.removeEventTypeSubscriber(EVENTS_OF_INTEREST, weakPcl);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -128,7 +129,7 @@ public final class AutopsyTreeChildFactory extends ChildFactory.Detachable<Objec
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (CollectionUtils.isNotEmpty(personManager.getHostsForPerson(null))) {
|
||||
if (CollectionUtils.isNotEmpty(personManager.getHostsWithoutPersons())) {
|
||||
nodes.add(new PersonGrouping(null));
|
||||
}
|
||||
} else {
|
||||
|
@ -115,14 +115,15 @@ public abstract class BaseChildFactory<T extends Content> extends ChildFactory.D
|
||||
isPageSizeChangeEvent = false;
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
onAdd();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
onRemove();
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ import org.openide.nodes.Node;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.WeakListeners;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
@ -76,15 +77,18 @@ public class DataSourcesNode extends DisplayableItemNode {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
Case.addEventTypeSubscriber(UPDATE_EVTS, pcl);
|
||||
Case.addEventTypeSubscriber(UPDATE_EVTS, weakPcl);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
Case.removeEventTypeSubscriber(UPDATE_EVTS, pcl);
|
||||
protected void finalize() throws Throwable{
|
||||
Case.removeEventTypeSubscriber(UPDATE_EVTS, weakPcl);
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2012-2020 Basis Technology Corp.
|
||||
* Copyright 2012-2021 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.WeakListeners;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
@ -313,21 +314,24 @@ public class EmailExtracted implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
emailResults.update();
|
||||
emailResults.addObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
protected void finalize() throws Throwable{
|
||||
super.finalize();
|
||||
IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
emailResults.deleteObserver(this);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2020 Basis Technology Corp.
|
||||
* Copyright 2011-2021 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.WeakListeners;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
@ -278,21 +279,24 @@ public class HashsetHits implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
hashsetResults.update();
|
||||
hashsetResults.addObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
hashsetResults.deleteObserver(this);
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ public class HostNode extends DisplayableItemNode {
|
||||
|
||||
private final Host host;
|
||||
private final Function<DataSourceGrouping, Node> dataSourceToNode;
|
||||
|
||||
|
||||
/**
|
||||
* Main constructor.
|
||||
*
|
||||
@ -77,7 +77,7 @@ public class HostNode extends DisplayableItemNode {
|
||||
this.host = host;
|
||||
this.dataSourceToNode = dataSourceToNode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Listener for handling DATA_SOURCE_ADDED / HOST_DELETED events.
|
||||
* A host may have been deleted as part of a merge, which means its data sources could
|
||||
@ -93,15 +93,19 @@ public class HostNode extends DisplayableItemNode {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(dataSourceAddedPcl, null);
|
||||
|
||||
@Override
|
||||
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
|
||||
protected void removeNotify() {
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.HOSTS_DELETED), dataSourceAddedPcl);
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.HOSTS_DELETED), weakPcl);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2020 Basis Technology Corp.
|
||||
* Copyright 2011-2021 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.WeakListeners;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
@ -271,21 +272,24 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
interestingResults.update();
|
||||
interestingResults.addObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
interestingResults.deleteObserver(this);
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@ import org.openide.nodes.Node;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.WeakListeners;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
@ -437,7 +438,8 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
keywordResults.deleteObserver(this);
|
||||
}
|
||||
|
||||
@ -504,22 +506,24 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
keywordResults.update();
|
||||
super.addNotify();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
super.removeNotify();
|
||||
protected void finalize() throws Throwable{
|
||||
IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -137,19 +137,22 @@ 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
|
||||
protected void addNotify() {
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.OS_ACCOUNTS_ADDED, Case.Events.OS_ACCOUNTS_DELETED), 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
|
||||
protected boolean createKeys(List<OsAccount> list) {
|
||||
if (skCase != null) {
|
||||
|
@ -92,6 +92,7 @@ public class PersonNode extends DisplayableItemNode {
|
||||
*/
|
||||
PersonChildren(Person person) {
|
||||
this.person = person;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -111,17 +112,20 @@ public class PersonNode extends DisplayableItemNode {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(hostAddedDeletedPcl, null);
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
Case.addEventTypeSubscriber(HOST_EVENTS_OF_INTEREST, hostAddedDeletedPcl);
|
||||
Case.addEventTypeSubscriber(HOST_EVENTS_OF_INTEREST, weakPcl);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
Case.removeEventTypeSubscriber(HOST_EVENTS_OF_INTEREST, hostAddedDeletedPcl);
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
Case.removeEventTypeSubscriber(HOST_EVENTS_OF_INTEREST, weakPcl);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected HostNode createNodeForKey(HostGrouping key) {
|
||||
return key == null ? null : new HostNode(key);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2019 Basis Technology Corp.
|
||||
* Copyright 2011-2021 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.WeakListeners;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
@ -213,6 +214,8 @@ public class Tags implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@ -221,21 +224,21 @@ public class Tags implements AutopsyVisitableItem {
|
||||
*/
|
||||
TagNameNodeFactory(long objId) {
|
||||
this.filteringDSObjId = objId;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl);
|
||||
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl);
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
|
||||
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, weakPcl);
|
||||
tagResults.update();
|
||||
tagResults.addObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||
Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl);
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
|
||||
Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, weakPcl);
|
||||
tagResults.deleteObserver(this);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2019 Basis Technology Corp.
|
||||
* Copyright 2011-2021 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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.util.NbBundle;
|
||||
import org.openide.util.Utilities;
|
||||
import org.openide.util.WeakListeners;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
@ -218,8 +219,8 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
abstract void handleDataAdded(ModuleDataEvent event);
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
super.removeNotify();
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
reviewStatusBus.unregister(ObservingChildren.this);
|
||||
}
|
||||
|
||||
@ -415,6 +416,8 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
|
||||
|
||||
@Subscribe
|
||||
@Override
|
||||
@ -473,18 +476,18 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
super.removeNotify();
|
||||
protected void finalize() throws Throwable {
|
||||
IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
super.addNotify();
|
||||
refresh(true);
|
||||
}
|
||||
@ -550,21 +553,22 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
super.addNotify();
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
super.removeNotify();
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -727,6 +731,9 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
|
||||
|
||||
|
||||
@Subscribe
|
||||
@Override
|
||||
@ -739,20 +746,21 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
void handleDataAdded(ModuleDataEvent event) {
|
||||
refresh(true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
super.addNotify();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
super.removeNotify();
|
||||
}
|
||||
|
||||
@ -881,21 +889,23 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
super.addNotify();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
super.removeNotify();
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@ -1095,21 +1105,23 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
super.addNotify();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
super.removeNotify();
|
||||
protected void finalize() throws Throwable{
|
||||
super.finalize();
|
||||
IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
|
@ -31,6 +31,7 @@ import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import javax.swing.AbstractAction;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.nodes.AbstractNode;
|
||||
import org.openide.explorer.ExplorerManager;
|
||||
import org.openide.explorer.view.TreeView;
|
||||
@ -84,7 +85,7 @@ public class ViewContextAction extends AbstractAction {
|
||||
* parent of the content, selecting the parent in the tree view, then
|
||||
* selecting the content in the results view.
|
||||
*
|
||||
* @param displayName The display name for the action.
|
||||
* @param displayName The display name for the action.
|
||||
* @param artifactNode The artifact node for the artifact.
|
||||
*/
|
||||
public ViewContextAction(String displayName, BlackboardArtifactNode artifactNode) {
|
||||
@ -106,9 +107,9 @@ public class ViewContextAction extends AbstractAction {
|
||||
* parent of the content, selecting the parent in the tree view, then
|
||||
* selecting the content in the results view.
|
||||
*
|
||||
* @param displayName The display name for the action.
|
||||
* @param displayName The display name for the action.
|
||||
* @param fileSystemContentNode The file system content node for the
|
||||
* content.
|
||||
* content.
|
||||
*/
|
||||
public ViewContextAction(String displayName, AbstractFsContentNode<? extends AbstractFile> fileSystemContentNode) {
|
||||
super(displayName);
|
||||
@ -121,9 +122,9 @@ public class ViewContextAction extends AbstractAction {
|
||||
* content, selecting the parent in the tree view, then selecting the
|
||||
* content in the results view.
|
||||
*
|
||||
* @param displayName The display name for the action.
|
||||
* @param displayName The display name for the action.
|
||||
* @param abstractAbstractFileNode The AbstractAbstractFileNode node for the
|
||||
* content.
|
||||
* content.
|
||||
*/
|
||||
public ViewContextAction(String displayName, AbstractAbstractFileNode<? extends AbstractFile> abstractAbstractFileNode) {
|
||||
super(displayName);
|
||||
@ -137,7 +138,7 @@ public class ViewContextAction extends AbstractAction {
|
||||
* content in the results view.
|
||||
*
|
||||
* @param displayName The display name for the action.
|
||||
* @param content The content.
|
||||
* @param content The content.
|
||||
*/
|
||||
public ViewContextAction(String displayName, Content content) {
|
||||
super(displayName);
|
||||
@ -149,7 +150,7 @@ public class ViewContextAction extends AbstractAction {
|
||||
* branch of the tree view to the level of the parent of the content,
|
||||
* selecting the parent in the tree view, then selecting the content in the
|
||||
* results view.
|
||||
*
|
||||
*
|
||||
* NOTE: This code will likely need updating in the event that the structure
|
||||
* of the nodes is changed (i.e. adding parent levels). Places to look when
|
||||
* changing node structure include:
|
||||
@ -168,176 +169,224 @@ public class ViewContextAction extends AbstractAction {
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
EventQueue.invokeLater(() -> {
|
||||
|
||||
/*
|
||||
* 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)
|
||||
&& (parentContent instanceof UnsupportedContent)) {
|
||||
Content parentContent = getParentContent(this.content);
|
||||
|
||||
if ((parentContent != null) && (parentContent instanceof UnsupportedContent)) {
|
||||
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
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the "Data Sources" node from the tree view.
|
||||
*/
|
||||
// Get the "Data Sources" node from the tree view.
|
||||
DirectoryTreeTopComponent treeViewTopComponent = DirectoryTreeTopComponent.findInstance();
|
||||
ExplorerManager treeViewExplorerMgr = treeViewTopComponent.getExplorerManager();
|
||||
|
||||
Node parentTreeViewNode = null;
|
||||
if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) { // 'Group by Data Source' view
|
||||
|
||||
SleuthkitCase skCase;
|
||||
String dsname;
|
||||
try {
|
||||
// get the objid/name of the datasource of the selected content.
|
||||
skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
|
||||
long contentDSObjid = content.getDataSource().getId();
|
||||
DataSource datasource = skCase.getDataSource(contentDSObjid);
|
||||
dsname = datasource.getName();
|
||||
Children rootChildren = treeViewExplorerMgr.getRootContext().getChildren();
|
||||
|
||||
if (null != parentContent) {
|
||||
// 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
|
||||
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
|
||||
data sources with that name, and make sure we find the correct one.
|
||||
*/
|
||||
List<Node> dataSourceLevelNodes = Stream.of(rootChildren.getNodes())
|
||||
.flatMap(rootNode -> getDataSourceLevelNodes(rootNode).stream())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (Node treeNode : dataSourceLevelNodes) {
|
||||
// in the root, look for a data source node with the name of interest
|
||||
if (!(treeNode.getName().equals(dsname))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// for this data source, get the "Data Sources" child node
|
||||
Node datasourceGroupingNode = treeNode.getChildren().findChild(DataSourceFilesNode.getNameIdentifier());
|
||||
|
||||
// check whether this is the data source we are looking for
|
||||
parentTreeViewNode = findParentNodeInTree(parentContent, datasourceGroupingNode);
|
||||
if (parentTreeViewNode != null) {
|
||||
// found the data source node
|
||||
break;
|
||||
}
|
||||
}
|
||||
} 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) {
|
||||
MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindNode());
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (parentContent != null) {
|
||||
if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) {
|
||||
parentTreeViewNode = getParentNodeGroupedByPersonHost(treeViewExplorerMgr, parentContent);
|
||||
} else {
|
||||
parentTreeViewNode = getParentNodeGroupedByDataSource(treeViewExplorerMgr, parentContent);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the child selection info of the parent tree node, then select
|
||||
* the parent node in the tree view. The results view will retrieve
|
||||
* this selection info and use it to complete this action when the
|
||||
* tree view top component responds to the selection of the parent
|
||||
* node by pushing it into the results view top component.
|
||||
*/
|
||||
DisplayableItemNode undecoratedParentNode = (DisplayableItemNode) ((DirectoryTreeFilterNode) parentTreeViewNode).getOriginal();
|
||||
undecoratedParentNode.setChildNodeSelectionInfo(new ContentNodeSelectionInfo(content));
|
||||
if (content instanceof BlackboardArtifact) {
|
||||
BlackboardArtifact artifact = ((BlackboardArtifact) content);
|
||||
long associatedId = artifact.getObjectID();
|
||||
try {
|
||||
Content associatedFileContent = artifact.getSleuthkitCase().getContentById(associatedId);
|
||||
undecoratedParentNode.setChildNodeSelectionInfo(new ContentNodeSelectionInfo(associatedFileContent));
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Could not find associated content from artifact with id %d", artifact.getId());
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
||||
TreeView treeView = treeViewTopComponent.getTree();
|
||||
treeView.expandNode(parentTreeViewNode);
|
||||
if (treeViewTopComponent.getSelectedNode().equals(parentTreeViewNode)) {
|
||||
//In the case where our tree view already has the destination directory selected
|
||||
//due to an optimization in the ExplorerManager.setExploredContextAndSelection method
|
||||
//the property change we listen for to call DirectoryTreeTopComponent.respondSelection
|
||||
//will not be sent so we call it manually ourselves after making
|
||||
//the directory listing the active tab.
|
||||
treeViewTopComponent.setDirectoryListingActive();
|
||||
treeViewTopComponent.respondSelection(treeViewExplorerMgr.getSelectedNodes(), new Node[]{parentTreeViewNode});
|
||||
} else {
|
||||
try {
|
||||
treeViewExplorerMgr.setExploredContextAndSelection(parentTreeViewNode, new Node[]{parentTreeViewNode});
|
||||
} catch (PropertyVetoException ex) {
|
||||
MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotSelectDirectory());
|
||||
logger.log(Level.SEVERE, "Failed to select the parent node in the tree view", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
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;
|
||||
String dsname;
|
||||
try {
|
||||
// get the objid/name of the datasource of the selected content.
|
||||
skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
|
||||
long contentDSObjid = parentContent.getDataSource().getId();
|
||||
DataSource datasource = skCase.getDataSource(contentDSObjid);
|
||||
dsname = datasource.getName();
|
||||
Children rootChildren = treeViewExplorerMgr.getRootContext().getChildren();
|
||||
|
||||
// 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
|
||||
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
|
||||
data sources with that name, and make sure we find the correct one.
|
||||
*/
|
||||
List<Node> dataSourceLevelNodes = Stream.of(rootChildren.getNodes(true))
|
||||
.flatMap(rootNode -> getDataSourceLevelNodes(rootNode).stream())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (Node treeNode : dataSourceLevelNodes) {
|
||||
// in the root, look for a data source node with the name of interest
|
||||
if (!(treeNode.getName().equals(dsname))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// for this data source, get the "Data Sources" child node
|
||||
Node datasourceGroupingNode = treeNode.getChildren().findChild(DataSourceFilesNode.getNameIdentifier());
|
||||
|
||||
// check whether this is the data source we are looking for
|
||||
Node parentTreeViewNode = findParentNodeInTree(parentContent, datasourceGroupingNode);
|
||||
if (parentTreeViewNode != null) {
|
||||
// found the data source node
|
||||
return parentTreeViewNode;
|
||||
}
|
||||
}
|
||||
} catch (NoCurrentCaseException | TskDataException | TskCoreException ex) {
|
||||
MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindNode());
|
||||
logger.log(Level.SEVERE, "Failed to locate data source node in tree.", ex); //NON-NLS
|
||||
}
|
||||
|
||||
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
|
||||
* the parent node in the tree view. The results view will retrieve
|
||||
* this selection info and use it to complete this action when the
|
||||
* tree view top component responds to the selection of the parent
|
||||
* node by pushing it into the results view top component.
|
||||
*/
|
||||
DisplayableItemNode undecoratedParentNode = (DisplayableItemNode) ((DirectoryTreeFilterNode) parentTreeViewNode).getOriginal();
|
||||
undecoratedParentNode.setChildNodeSelectionInfo(new ContentNodeSelectionInfo(content));
|
||||
if (content instanceof BlackboardArtifact) {
|
||||
BlackboardArtifact artifact = ((BlackboardArtifact) content);
|
||||
long associatedId = artifact.getObjectID();
|
||||
try {
|
||||
Content associatedFileContent = artifact.getSleuthkitCase().getContentById(associatedId);
|
||||
undecoratedParentNode.setChildNodeSelectionInfo(new ContentNodeSelectionInfo(associatedFileContent));
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Could not find associated content from artifact with id %d", artifact.getId());
|
||||
}
|
||||
}
|
||||
|
||||
TreeView treeView = treeViewTopComponent.getTree();
|
||||
treeView.expandNode(parentTreeViewNode);
|
||||
if (treeViewTopComponent.getSelectedNode().equals(parentTreeViewNode)) {
|
||||
//In the case where our tree view already has the destination directory selected
|
||||
//due to an optimization in the ExplorerManager.setExploredContextAndSelection method
|
||||
//the property change we listen for to call DirectoryTreeTopComponent.respondSelection
|
||||
//will not be sent so we call it manually ourselves after making
|
||||
//the directory listing the active tab.
|
||||
treeViewTopComponent.setDirectoryListingActive();
|
||||
treeViewTopComponent.respondSelection(treeViewExplorerMgr.getSelectedNodes(), new Node[]{parentTreeViewNode});
|
||||
} else {
|
||||
try {
|
||||
treeViewExplorerMgr.setExploredContextAndSelection(parentTreeViewNode, new Node[]{parentTreeViewNode});
|
||||
} catch (PropertyVetoException ex) {
|
||||
MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotSelectDirectory());
|
||||
logger.log(Level.SEVERE, "Failed to select the parent node in the tree view", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the node has lookup of host or person, returns children. If not, just
|
||||
* returns itself.
|
||||
*
|
||||
* @param node The node.
|
||||
*
|
||||
* @return The child nodes that are at the data source level.
|
||||
*/
|
||||
private List<Node> getDataSourceLevelNodes(Node node) {
|
||||
if (node == null) {
|
||||
return Collections.emptyList();
|
||||
} else if (node.getLookup().lookup(Host.class) != null ||
|
||||
node.getLookup().lookup(Person.class) != null ||
|
||||
DataSourcesNode.getNameIdentifier().equals(node.getLookup().lookup(String.class)) ||
|
||||
PersonNode.getUnknownPersonId().equals(node.getLookup().lookup(String.class))) {
|
||||
} else if (node.getLookup().lookup(Host.class) != null
|
||||
|| node.getLookup().lookup(Person.class) != null
|
||||
|| DataSourcesNode.getNameIdentifier().equals(node.getLookup().lookup(String.class))
|
||||
|| PersonNode.getUnknownPersonId().equals(node.getLookup().lookup(String.class))) {
|
||||
Children children = node.getChildren();
|
||||
Node[] childNodes = children == null ? null : children.getNodes();
|
||||
Node[] childNodes = children == null ? null : children.getNodes(true);
|
||||
if (childNodes == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return Stream.of(node.getChildren().getNodes())
|
||||
return Stream.of(node.getChildren().getNodes(true))
|
||||
.flatMap(parent -> getDataSourceLevelNodes(parent).stream())
|
||||
.collect(Collectors.toList());
|
||||
} else {
|
||||
@ -350,7 +399,8 @@ public class ViewContextAction extends AbstractAction {
|
||||
* of the specified content.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
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);
|
||||
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
|
||||
* simply discards "extra" ancestor nodes not shown in the tree,
|
||||
@ -387,8 +442,9 @@ public class ViewContextAction extends AbstractAction {
|
||||
Node parentTreeViewNode = null;
|
||||
for (int i = 0; i < ancestorChildren.getNodesCount(); i++) {
|
||||
Node ancestorNode = ancestorChildren.getNodeAt(i);
|
||||
for (int j = 0; j < treeNodeChildren.getNodesCount(); j++) {
|
||||
Node treeNode = treeNodeChildren.getNodeAt(j);
|
||||
Node[] treeNodeChilds = treeNodeChildren.getNodes(true);
|
||||
for (int j = 0; j < treeNodeChilds.length; j++) {
|
||||
Node treeNode = treeNodeChilds[j];
|
||||
if (ancestorNode.getName().equals(treeNode.getName())) {
|
||||
parentTreeViewNode = treeNode;
|
||||
treeNodeChildren = treeNode.getChildren();
|
||||
|
Loading…
x
Reference in New Issue
Block a user