From a45de89e374f59748ecc90964d5f48018eab398c Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 20 Apr 2020 09:56:32 -0400 Subject: [PATCH 1/4] refactoring of PinnedAccountModel --- .../communications/AbstractCVTAction.java | 5 +- .../autopsy/communications/CVTEvents.java | 21 +++---- .../communications/CommunicationsGraph.java | 56 ++++++++++--------- .../communications/PinnedAccountModel.java | 11 ++-- .../autopsy/communications/StateManager.java | 14 +++-- .../communications/VisualizationPanel.java | 2 +- 6 files changed, 60 insertions(+), 49 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/AbstractCVTAction.java b/Core/src/org/sleuthkit/autopsy/communications/AbstractCVTAction.java index ef751d262c..a02f0c0e86 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/AbstractCVTAction.java +++ b/Core/src/org/sleuthkit/autopsy/communications/AbstractCVTAction.java @@ -24,6 +24,7 @@ import javax.swing.ImageIcon; import javax.swing.JMenuItem; import org.openide.util.Utilities; import org.openide.util.actions.Presenter; +import org.sleuthkit.datamodel.AccountDeviceInstance; /** * Base class for actions that act on the selected AccountDeviceInstanceKeys. @@ -37,8 +38,8 @@ abstract class AbstractCVTAction extends AbstractAction implements Presenter.Pop * * @return The selected accounts */ - Collection getSelectedAccounts() { - return Utilities.actionsGlobalContext().lookupAll(AccountDeviceInstanceKey.class); + Collection getSelectedAccounts() { + return Utilities.actionsGlobalContext().lookupAll(AccountDeviceInstance.class); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/communications/CVTEvents.java b/Core/src/org/sleuthkit/autopsy/communications/CVTEvents.java index ee7224b673..ae3735e30f 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/CVTEvents.java +++ b/Core/src/org/sleuthkit/autopsy/communications/CVTEvents.java @@ -24,6 +24,7 @@ import java.util.Collection; import org.sleuthkit.autopsy.communications.FiltersPanel.DateControlState; import org.sleuthkit.datamodel.CommunicationsFilter; import org.sleuthkit.autopsy.communications.StateManager.CommunicationsState; +import org.sleuthkit.datamodel.AccountDeviceInstance; /** * Provide the singleton EventBus. @@ -73,19 +74,19 @@ final class CVTEvents { */ static final class PinAccountsEvent { - private final ImmutableSet accountDeviceInstances; + private final ImmutableSet accounInstances; private final boolean replace; public boolean isReplace() { return replace; } - ImmutableSet getAccountDeviceInstances() { - return accountDeviceInstances; + ImmutableSet getAccountDeviceInstances() { + return accounInstances; } - PinAccountsEvent(Collection accountDeviceInstances, boolean replace) { - this.accountDeviceInstances = ImmutableSet.copyOf(accountDeviceInstances); + PinAccountsEvent(Collection accountDeviceInstances, boolean replace) { + this.accounInstances = ImmutableSet.copyOf(accountDeviceInstances); this.replace = replace; } } @@ -95,14 +96,14 @@ final class CVTEvents { */ static final class UnpinAccountsEvent { - private final ImmutableSet accountDeviceInstances; + private final ImmutableSet accountInstances; - public ImmutableSet getAccountDeviceInstances() { - return accountDeviceInstances; + public ImmutableSet getAccountDeviceInstances() { + return accountInstances; } - UnpinAccountsEvent(Collection accountDeviceInstances) { - this.accountDeviceInstances = ImmutableSet.copyOf(accountDeviceInstances); + UnpinAccountsEvent(Collection accountDeviceInstances) { + this.accountInstances = ImmutableSet.copyOf(accountDeviceInstances); } } diff --git a/Core/src/org/sleuthkit/autopsy/communications/CommunicationsGraph.java b/Core/src/org/sleuthkit/autopsy/communications/CommunicationsGraph.java index 716d00656c..f88edeedcf 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/CommunicationsGraph.java +++ b/Core/src/org/sleuthkit/autopsy/communications/CommunicationsGraph.java @@ -32,6 +32,7 @@ import java.io.InputStreamReader; import java.io.StringWriter; import java.net.URL; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -147,7 +148,7 @@ final class CommunicationsGraph extends mxGraph { scopes.put("accountName", adiKey.getAccountDeviceInstance().getAccount().getTypeSpecificID()); scopes.put("size", Math.round(Math.log(adiKey.getMessageCount()) + 5)); scopes.put("iconFileName", CommunicationsGraph.class.getResource(Utils.getIconFilePath(adiKey.getAccountDeviceInstance().getAccount().getAccountType()))); - scopes.put("pinned", pinnedAccountModel.isAccountPinned(adiKey)); + scopes.put("pinned", pinnedAccountModel.isAccountPinned(adiKey.getAccountDeviceInstance())); scopes.put("MARKER_PIN_URL", MARKER_PIN_URL); scopes.put("locked", lockedVertexModel.isVertexLocked((mxCell) cell)); scopes.put("LOCK_URL", LOCK_URL); @@ -172,7 +173,7 @@ final class CommunicationsGraph extends mxGraph { scopes.put("accountName", adiKey.getAccountDeviceInstance().getAccount().getTypeSpecificID()); scopes.put("relationships", 12);// Math.round(Math.log(adiKey.getMessageCount()) + 5)); scopes.put("iconFileName", CommunicationsGraph.class.getResource(Utils.getIconFilePath(adiKey.getAccountDeviceInstance().getAccount().getAccountType()))); - scopes.put("pinned", pinnedAccountModel.isAccountPinned(adiKey)); + scopes.put("pinned", pinnedAccountModel.isAccountPinned(adiKey.getAccountDeviceInstance())); scopes.put("MARKER_PIN_URL", MARKER_PIN_URL); scopes.put("locked", lockedVertexModel.isVertexLocked((mxCell) cell)); scopes.put("LOCK_URL", LOCK_URL); @@ -199,16 +200,23 @@ final class CommunicationsGraph extends mxGraph { lockedVertexModel.clear(); } - private mxCell getOrCreateVertex(AccountDeviceInstanceKey accountDeviceInstanceKey) { - final AccountDeviceInstance accountDeviceInstance = accountDeviceInstanceKey.getAccountDeviceInstance(); + private mxCell getOrCreateVertex(AccountDeviceInstance adi, CommunicationsManager commsManager, CommunicationsFilter currentFilter) { + final AccountDeviceInstance accountDeviceInstance = adi; final String name = accountDeviceInstance.getAccount().getTypeSpecificID(); final mxCell vertex = nodeMap.computeIfAbsent(name + accountDeviceInstance.getDeviceId(), vertexName -> { - double size = Math.sqrt(accountDeviceInstanceKey.getMessageCount()) + 10; + long adiRelationshipsCount = 1; + try { + adiRelationshipsCount = commsManager.getRelationshipSourcesCount(accountDeviceInstance, currentFilter); + } catch (TskCoreException tskCoreException) { + logger.log(Level.SEVERE, "Error", tskCoreException); + } + + double size = Math.sqrt(adiRelationshipsCount) + 10; mxCell newVertex = (mxCell) insertVertex( getDefaultParent(), - name, accountDeviceInstanceKey, + name, adi, Math.random() * 400, Math.random() * 400, size, @@ -219,9 +227,11 @@ final class CommunicationsGraph extends mxGraph { } @SuppressWarnings("unchecked") - private mxCell addOrUpdateEdge(long relSources, AccountDeviceInstanceKey account1, AccountDeviceInstanceKey account2) { - mxCell vertex1 = getOrCreateVertex(account1); - mxCell vertex2 = getOrCreateVertex(account2); + private mxCell addOrUpdateEdge(long relSources, + AccountDeviceInstance account1, AccountDeviceInstance account2, + CommunicationsManager commsManager, CommunicationsFilter currentFilter) { + mxCell vertex1 = getOrCreateVertex(account1, commsManager, currentFilter); + mxCell vertex2 = getOrCreateVertex(account2, commsManager, currentFilter); Object[] edgesBetween = getEdgesBetween(vertex1, vertex2); mxCell edge; if (edgesBetween.length == 0) { @@ -260,28 +270,24 @@ final class CommunicationsGraph extends mxGraph { /** * set to keep track of accounts related to pinned accounts */ - final Map relatedAccounts = new HashMap<>(); - for (final AccountDeviceInstanceKey adiKey : pinnedAccountModel.getPinnedAccounts()) { + final Set relatedAccounts = new HashSet<>(); + for (final AccountDeviceInstance adi : pinnedAccountModel.getPinnedAccounts()) { if (isCancelled()) { break; } //get accounts related to pinned account final List relatedAccountDeviceInstances - = commsManager.getRelatedAccountDeviceInstances(adiKey.getAccountDeviceInstance(), currentFilter); - relatedAccounts.put(adiKey.getAccountDeviceInstance(), adiKey); - getOrCreateVertex(adiKey); + = commsManager.getRelatedAccountDeviceInstances(adi, currentFilter); + relatedAccounts.add(adi); + getOrCreateVertex(adi, commsManager, currentFilter); + + for (final AccountDeviceInstance relatedADI : relatedAccountDeviceInstances) + relatedAccounts.add(relatedADI); - for (final AccountDeviceInstance relatedADI : relatedAccountDeviceInstances) { - final long adiRelationshipsCount = commsManager.getRelationshipSourcesCount(relatedADI, currentFilter); - final AccountDeviceInstanceKey relatedADIKey = new AccountDeviceInstanceKey(relatedADI, currentFilter, adiRelationshipsCount); - relatedAccounts.put(relatedADI, relatedADIKey); //store related accounts - } progressIndicator.progress(++progressCounter); } - Set accounts = relatedAccounts.keySet(); - - Map relationshipCounts = commsManager.getRelationshipCountsPairwise(accounts, currentFilter); + Map relationshipCounts = commsManager.getRelationshipCountsPairwise(relatedAccounts, currentFilter); int total = relationshipCounts.size(); int progress = 0; @@ -290,12 +296,12 @@ final class CommunicationsGraph extends mxGraph { for (Map.Entry entry : relationshipCounts.entrySet()) { Long count = entry.getValue(); AccountPair relationshipKey = entry.getKey(); - AccountDeviceInstanceKey account1 = relatedAccounts.get(relationshipKey.getFirst()); - AccountDeviceInstanceKey account2 = relatedAccounts.get(relationshipKey.getSecond()); + AccountDeviceInstance account1 = relationshipKey.getFirst(); + AccountDeviceInstance account2 = relationshipKey.getSecond(); if (pinnedAccountModel.isAccountPinned(account1) || pinnedAccountModel.isAccountPinned(account2)) { - mxCell addEdge = addOrUpdateEdge(count, account1, account2); + mxCell addEdge = addOrUpdateEdge(count, account1, account2, commsManager, currentFilter); progressText = addEdge.getId(); } progressIndicator.progress(progressText, progress++); diff --git a/Core/src/org/sleuthkit/autopsy/communications/PinnedAccountModel.java b/Core/src/org/sleuthkit/autopsy/communications/PinnedAccountModel.java index c9fe899c3f..9221a487cb 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/PinnedAccountModel.java +++ b/Core/src/org/sleuthkit/autopsy/communications/PinnedAccountModel.java @@ -22,6 +22,7 @@ import com.google.common.collect.ImmutableSet; import com.google.common.eventbus.EventBus; import java.util.HashSet; import java.util.Set; +import org.sleuthkit.datamodel.AccountDeviceInstance; /** * Model of what accounts are pinned to a visualization. @@ -34,7 +35,7 @@ class PinnedAccountModel { * to pinned accounts and pass the filters are show. Pinning accounts is the * primary way to populate the graph. */ - private final Set pinnedAccountDevices = new HashSet<>(); + private final Set pinnedAccountDevices = new HashSet<>(); private final EventBus eventBus = new EventBus(); @@ -46,7 +47,7 @@ class PinnedAccountModel { eventBus.unregister(handler); } - boolean isAccountPinned(AccountDeviceInstanceKey account) { + boolean isAccountPinned(AccountDeviceInstance account) { return pinnedAccountDevices.contains(account); } @@ -57,7 +58,7 @@ class PinnedAccountModel { * * @param accountDeviceInstances The accounts to unpin. */ - void unpinAccount(Set accountDeviceInstances) { + void unpinAccount(Set accountDeviceInstances) { pinnedAccountDevices.removeAll(accountDeviceInstances); } @@ -68,7 +69,7 @@ class PinnedAccountModel { * * @param accountDeviceInstances The accounts to pin. */ - void pinAccount(Set accountDeviceInstances) { + void pinAccount(Set accountDeviceInstances) { pinnedAccountDevices.addAll(accountDeviceInstances); } @@ -86,7 +87,7 @@ class PinnedAccountModel { pinnedAccountDevices.clear(); } - ImmutableSet getPinnedAccounts() { + ImmutableSet getPinnedAccounts() { return ImmutableSet.copyOf(pinnedAccountDevices); } diff --git a/Core/src/org/sleuthkit/autopsy/communications/StateManager.java b/Core/src/org/sleuthkit/autopsy/communications/StateManager.java index c84a5beb79..ca1d902153 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/StateManager.java +++ b/Core/src/org/sleuthkit/autopsy/communications/StateManager.java @@ -23,6 +23,8 @@ import java.util.HashSet; import java.util.Set; import org.sleuthkit.autopsy.communications.FiltersPanel.DateControlState; import org.sleuthkit.autopsy.coreutils.History; +import org.sleuthkit.datamodel.Account; +import org.sleuthkit.datamodel.AccountDeviceInstance; import org.sleuthkit.datamodel.CommunicationsFilter; /** @@ -51,11 +53,11 @@ final class StateManager { @Subscribe void pinAccount(CVTEvents.PinAccountsEvent pinEvent) { if(pinEvent.isReplace()){ - HashSet pinnedList = new HashSet<>(); + HashSet pinnedList = new HashSet<>(); pinnedList.addAll(pinEvent.getAccountDeviceInstances()); historyManager.advance(new CommunicationsState(comFilter, pinnedList, -1, currentStartState, currentEndState)); } else { - HashSet pinnedList = new HashSet<>(); + HashSet pinnedList = new HashSet<>(); pinnedList.addAll(pinEvent.getAccountDeviceInstances()); pinnedList.addAll(pinModel.getPinnedAccounts()); @@ -74,7 +76,7 @@ final class StateManager { @Subscribe void unpinAccounts(CVTEvents.UnpinAccountsEvent pinEvent) { - HashSet pinnedList = new HashSet<>(); + HashSet pinnedList = new HashSet<>(); pinnedList.addAll(pinModel.getPinnedAccounts()); pinnedList.removeAll(pinEvent.getAccountDeviceInstances()); @@ -135,7 +137,7 @@ final class StateManager { */ final class CommunicationsState{ private final CommunicationsFilter communcationFilter; - private final Set pinnedList; + private final Set pinnedList; private final double zoomValue; private final DateControlState startDateState; private final DateControlState endDateState; @@ -149,7 +151,7 @@ final class StateManager { * @param zoomValue Double value of the current graph scale */ protected CommunicationsState(CommunicationsFilter communcationFilter, - Set pinnedList, double zoomValue, + Set pinnedList, double zoomValue, DateControlState startDateState, DateControlState endDateState){ this.pinnedList = pinnedList; this.communcationFilter = communcationFilter; @@ -172,7 +174,7 @@ final class StateManager { * * @return Set of AccountDeviceInstanceKey */ - public Set getPinnedList(){ + public Set getPinnedList(){ return pinnedList; } diff --git a/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java b/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java index 1799ebcb8d..51005878ec 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java @@ -1100,7 +1100,7 @@ final public class VisualizationPanel extends JPanel { } else { jPopupMenu.add(new JMenuItem(new LockAction(selectedVertices))); } - if (pinnedAccountModel.isAccountPinned(adiKey)) { + if (pinnedAccountModel.isAccountPinned(adiKey.getAccountDeviceInstance())) { jPopupMenu.add(UnpinAccountsAction.getInstance().getPopupPresenter()); } else { jPopupMenu.add(PinAccountsAction.getInstance().getPopupPresenter()); From 1f3acd3647928983aa48bfb50d042746dd74f380 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 20 Apr 2020 10:22:49 -0400 Subject: [PATCH 2/4] some bug fixes --- .../sleuthkit/autopsy/communications/AbstractCVTAction.java | 6 +++++- .../autopsy/communications/CommunicationsGraph.java | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/AbstractCVTAction.java b/Core/src/org/sleuthkit/autopsy/communications/AbstractCVTAction.java index a02f0c0e86..95c2d43bbb 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/AbstractCVTAction.java +++ b/Core/src/org/sleuthkit/autopsy/communications/AbstractCVTAction.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.communications; import java.util.Collection; +import java.util.stream.Collectors; import javax.swing.AbstractAction; import javax.swing.ImageIcon; import javax.swing.JMenuItem; @@ -39,7 +40,10 @@ abstract class AbstractCVTAction extends AbstractAction implements Presenter.Pop * @return The selected accounts */ Collection getSelectedAccounts() { - return Utilities.actionsGlobalContext().lookupAll(AccountDeviceInstance.class); + return Utilities.actionsGlobalContext().lookupAll(AccountDeviceInstanceKey.class) + .stream() + .map((adiKey -> adiKey.getAccountDeviceInstance())) + .collect(Collectors.toSet()); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/communications/CommunicationsGraph.java b/Core/src/org/sleuthkit/autopsy/communications/CommunicationsGraph.java index f88edeedcf..38a20d07e5 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/CommunicationsGraph.java +++ b/Core/src/org/sleuthkit/autopsy/communications/CommunicationsGraph.java @@ -213,10 +213,11 @@ final class CommunicationsGraph extends mxGraph { } double size = Math.sqrt(adiRelationshipsCount) + 10; - + AccountDeviceInstanceKey adiKey = new AccountDeviceInstanceKey(adi, currentFilter, adiRelationshipsCount); + mxCell newVertex = (mxCell) insertVertex( getDefaultParent(), - name, adi, + name, adiKey, Math.random() * 400, Math.random() * 400, size, From 09f46d2b1c5638fea1235f53efd01652cbe76c5f Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 20 Apr 2020 11:01:01 -0400 Subject: [PATCH 3/4] remove unused import --- Core/src/org/sleuthkit/autopsy/communications/StateManager.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/StateManager.java b/Core/src/org/sleuthkit/autopsy/communications/StateManager.java index ca1d902153..3f24a98764 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/StateManager.java +++ b/Core/src/org/sleuthkit/autopsy/communications/StateManager.java @@ -23,7 +23,6 @@ import java.util.HashSet; import java.util.Set; import org.sleuthkit.autopsy.communications.FiltersPanel.DateControlState; import org.sleuthkit.autopsy.coreutils.History; -import org.sleuthkit.datamodel.Account; import org.sleuthkit.datamodel.AccountDeviceInstance; import org.sleuthkit.datamodel.CommunicationsFilter; From 36ced0b39113c1295607823a1d07a4e688c81d15 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 23 Apr 2020 10:37:38 -0400 Subject: [PATCH 4/4] improved logging --- .../sleuthkit/autopsy/communications/CommunicationsGraph.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/CommunicationsGraph.java b/Core/src/org/sleuthkit/autopsy/communications/CommunicationsGraph.java index 38a20d07e5..f07d4d52ab 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/CommunicationsGraph.java +++ b/Core/src/org/sleuthkit/autopsy/communications/CommunicationsGraph.java @@ -209,7 +209,7 @@ final class CommunicationsGraph extends mxGraph { try { adiRelationshipsCount = commsManager.getRelationshipSourcesCount(accountDeviceInstance, currentFilter); } catch (TskCoreException tskCoreException) { - logger.log(Level.SEVERE, "Error", tskCoreException); + logger.log(Level.SEVERE, "There was an error fetching relationships for the node: " + accountDeviceInstance, tskCoreException); } double size = Math.sqrt(adiRelationshipsCount) + 10;