Merge branch 'accounts_table_column_widths' into 865-build-out-flters-host-container

# Conflicts:
#	Core/src/org/sleuthkit/autopsy/communications/AccountNode.java
This commit is contained in:
millmanorama 2017-10-26 13:04:45 +02:00
commit 7c463d19aa
8 changed files with 174 additions and 129 deletions

View File

@ -0,0 +1,92 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.communications;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Sheet;
import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.datamodel.NodeProperty;
import org.sleuthkit.datamodel.AccountDeviceInstance;
import org.sleuthkit.datamodel.CommunicationsFilter;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Node to represent an Account in the AccountsBrowser
*/
class AccountDeviceInstanceNode extends AbstractNode {
private static final Logger LOGGER = Logger.getLogger(AccountDeviceInstanceNode.class.getName());
private final AccountDeviceInstance accountDeviceInstance;
AccountDeviceInstanceNode(AccountDeviceInstance accountDeviceInstance) {
super(Children.LEAF, Lookups.fixed(accountDeviceInstance));
this.accountDeviceInstance = accountDeviceInstance;
setName(accountDeviceInstance.getAccount().getAccountUniqueID());
setIconBaseWithExtension("org/sleuthkit/autopsy/communications/images/"
+ AccountUtils.getIconFileName(accountDeviceInstance.getAccount().getAccountType()));
}
@Override
@NbBundle.Messages({
"AccountNode.device=Device",
"AccountNode.accountName=Account",
"AccountNode.accountType=Type",
"AccountNode.messageCount=Msg Count"})
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set properties = s.get(Sheet.PROPERTIES);
if (properties == null) {
properties = Sheet.createPropertiesSet();
s.put(properties);
}
// RAMAN TBD: need to figure out how to get the right filters here
// We talked about either creating a wrapper class around AccountDeviceInstance to push the selected filters
// Or some kind of static access to pull the selected filters
long msgCount = 0;
try {
CommunicationsFilter filter = null;
msgCount = Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager().getRelationshipsCount(filter, accountDeviceInstance);
} catch (TskCoreException ex) {
LOGGER.log(Level.WARNING, "Failed to get message count for account", ex); //NON-NLS
}
properties.put(new NodeProperty<>("type",
Bundle.AccountNode_accountType(),
"type",
accountDeviceInstance.getAccount().getAccountType().getDisplayName())); // NON-NLS
properties.put(new NodeProperty<>("count",
Bundle.AccountNode_messageCount(),
"count",
msgCount)); // NON-NLS
properties.put(new NodeProperty<>("device",
Bundle.AccountNode_device(),
"device",
accountDeviceInstance.getDeviceId())); // NON-NLS
return s;
}
}

View File

@ -1,77 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.communications;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Sheet;
import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.datamodel.NodeProperty;
import org.sleuthkit.datamodel.Account;
/**
* Node to represent an Account in the AccountsBrowser
*
* TODO: This will change to AccountDeviceInstanceNode and wrap a
* AccountDeviceInstance. This will let us populate the device field. What about
* the counts? Are we going to end up doing another query for each object?
*/
class AccountNode extends AbstractNode {
private final Account account;
AccountNode(Account account) {
super(Children.LEAF, Lookups.fixed(account));
this.account = account;
setName(account.getAccountUniqueID());
setIconBaseWithExtension("org/sleuthkit/autopsy/communications/images/" + AccountUtils.getIconFileName(account.getAccountType()));
}
@Override
@NbBundle.Messages({
"AccountNode.device=Device",
"AccountNode.accountName=Account",
"AccountNode.accountType=Type",
"AccountNode.messageCount=Msg Count"})
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set properties = s.get(Sheet.PROPERTIES);
if (properties == null) {
properties = Sheet.createPropertiesSet();
s.put(properties);
}
properties.put(new NodeProperty<>("type",
Bundle.AccountNode_accountType(),
"type",
account.getAccountType().getDisplayName())); // NON-NLS
properties.put(new NodeProperty<>("count",
Bundle.AccountNode_messageCount(),
"count",
1)); // NON-NLS //dummy value
//TODO: uncomment and correct this when this class changes to AccountDeviceInstanceNode
// properties.put(new NodeProperty<>("device",
// Bundle.AccountNode_device(),
// "device",
// account.)); // NON-NLS
return s;
}
}

View File

@ -1,16 +1,32 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
* Autopsy Forensic Browser
*
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.communications;
import org.sleuthkit.datamodel.Account;
/**
*
* Utility class with helpers for dealing with accounts.
*/
public class AccountUtils {
class AccountUtils {
private AccountUtils() {
}
/**
* The file name of the icon for the given Account Type. Will not include
@ -19,30 +35,29 @@ public class AccountUtils {
* @return The file name of the icon for the given Account Type.
*/
static final String getIconFileName(Account.Type type) {
if (type == Account.Type.CREDIT_CARD) {
if (type.equals(Account.Type.CREDIT_CARD)) {
return "credit-card.png";
} else if (type == Account.Type.DEVICE) {
} else if (type.equals(Account.Type.DEVICE)) {
return "image.png";
} else if (type == Account.Type.EMAIL) {
} else if (type.equals(Account.Type.EMAIL)) {
return "email.png";
} else if (type == Account.Type.FACEBOOK) {
} else if (type.equals(Account.Type.FACEBOOK)) {
return "facebook.png";
} else if (type == Account.Type.INSTAGRAM) {
} else if (type.equals(Account.Type.INSTAGRAM)) {
return "instagram.png";
} else if (type == Account.Type.MESSAGING_APP) {
} else if (type.equals(Account.Type.MESSAGING_APP)) {
return "messaging.png";
} else if (type == Account.Type.PHONE) {
} else if (type.equals(Account.Type.PHONE)) {
return "phone.png";
} else if (type == Account.Type.TWITTER) {
} else if (type.equals(Account.Type.TWITTER)) {
return "twitter.png";
} else if (type == Account.Type.WEBSITE) {
} else if (type.equals(Account.Type.WEBSITE)) {
return "web-file.png";
} else if (type == Account.Type.WHATSAPP) {
} else if (type.equals(Account.Type.WHATSAPP)) {
return "WhatsApp.png";
} else {
//there could be a default icon instead...
throw new IllegalArgumentException("Unknown Account.Type: " + type.getTypeName());
}
}
}

View File

@ -21,14 +21,15 @@ package org.sleuthkit.autopsy.communications;
import java.awt.Component;
import javax.swing.JPanel;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.table.TableCellRenderer;
import org.netbeans.swing.outline.DefaultOutlineModel;
import org.netbeans.swing.outline.Outline;
import org.openide.explorer.ExplorerManager;
/**
* A panel that goes in the Browse tab of the CVT. Has a OutlineView that shows
* information about Accounts.
* A panel that goes in the Browse tab of the Communications Visualization Tool.
* Hosts an OutlineView that shows information about Accounts.
*/
public class AccountsBrowser extends JPanel {
@ -52,9 +53,7 @@ public class AccountsBrowser extends JPanel {
outline.setRootVisible(false);
((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.AccountNode_accountName());
outline.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
outline.setColumnSorted(3, false, 1); //it would be could if the column index wasn't hardcoded
// setColumnWidths();
outline.setColumnSorted(3, false, 1); //it would be nice if the column index wasn't hardcoded
}
@Override
@ -63,9 +62,9 @@ public class AccountsBrowser extends JPanel {
em = ExplorerManager.find(this);
em.addPropertyChangeListener(evt -> {
if (ExplorerManager.PROP_ROOT_CONTEXT.equals(evt.getPropertyName())) {
setColumnWidths();
SwingUtilities.invokeLater(this::setColumnWidths);
} else if (ExplorerManager.PROP_EXPLORED_CONTEXT.equals(evt.getPropertyName())) {
setColumnWidths();
SwingUtilities.invokeLater(this::setColumnWidths);
}
});
}
@ -74,10 +73,11 @@ public class AccountsBrowser extends JPanel {
int margin = 4;
int padding = 8;
final int rows = Math.min(100, outline.getRowCount());
for (int column = 0; column < outline.getModel().getColumnCount(); column++) {
int columnWidthLimit = 500;
int columnWidth = 0;
final int rows = Math.min(100, outline.getRowCount());
// find the maximum width needed to fit the values for the first 100 rows, at most
for (int row = 0; row < rows; row++) {

View File

@ -22,15 +22,15 @@ import java.util.Collections;
import java.util.List;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.sleuthkit.datamodel.Account;
import org.sleuthkit.datamodel.AccountDeviceInstance;
class AccountsNodeChildren extends Children.Keys<Account> {
class AccountsDeviceInstanceChildren extends Children.Keys<AccountDeviceInstance> {
private final List<Account> accounts;
private final List<AccountDeviceInstance> accountDeviceInstances;
AccountsNodeChildren(List<Account> accounts) {
AccountsDeviceInstanceChildren(List<AccountDeviceInstance> accountDeviceInstances) {
super(true);
this.accounts = accounts;
this.accountDeviceInstances = accountDeviceInstances;
}
@Override
@ -42,7 +42,7 @@ class AccountsNodeChildren extends Children.Keys<Account> {
@Override
protected void addNotify() {
super.addNotify();
setKeys(accounts);
setKeys(accountDeviceInstances);
}
//These are the methods for ChildFactory. I am going to keep them around but commented until we make a final descision.
@ -54,10 +54,10 @@ class AccountsNodeChildren extends Children.Keys<Account> {
//
// @Override
// protected Node createNodeForKey(Account key) {
// return new AccountNode(key);
// return new AccountDeviceInstanceNode(key);
// }
@Override
protected Node[] createNodes(Account key) {
return new Node[]{new AccountNode(key)};
protected Node[] createNodes(AccountDeviceInstance key) {
return new Node[]{new AccountDeviceInstanceNode(key)};
}
}

View File

@ -124,7 +124,6 @@ public final class CVTTopComponent extends TopComponent implements ExplorerManag
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JTabbedPane BrowseVisualizeTabPane;
private javax.swing.JSplitPane HSplitPane;

View File

@ -22,8 +22,8 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.stream.Collectors;
import javax.swing.JCheckBox;
import org.openide.explorer.ExplorerManager;
import org.openide.nodes.AbstractNode;
@ -31,8 +31,11 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
import org.sleuthkit.datamodel.Account;
import org.sleuthkit.datamodel.AccountDeviceInstance;
import org.sleuthkit.datamodel.CommunicationsFilter;
import org.sleuthkit.datamodel.CommunicationsManager;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.DeviceFilter;
import org.sleuthkit.datamodel.TskCoreException;
/**
@ -78,6 +81,12 @@ public class FiltersPanel extends javax.swing.JPanel {
accountTypePane.add(jCheckBox);
accountTypeMap.put(type, jCheckBox);
});
}
@Override
public void addNotify() {
super.addNotify();
em = ExplorerManager.find(this);
/**
* Populate the devices filter widgets
@ -92,12 +101,7 @@ public class FiltersPanel extends javax.swing.JPanel {
} catch (TskCoreException tskCoreException) {
logger.log(Level.SEVERE, "There was a error loading the datasources for the case.", tskCoreException);
}
}
@Override
public void addNotify() {
super.addNotify();
em = ExplorerManager.find(this);
}
/**
@ -288,20 +292,35 @@ public class FiltersPanel extends javax.swing.JPanel {
* to AccountDeviceInstances
*/
try {
final CommunicationsManager communicationsManager = Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager();
List<AccountDeviceInstance> accountDeviceInstances = new ArrayList<>();
CommunicationsFilter commsFilter = new CommunicationsFilter();
commsFilter.addAndFilter(getDevceFilter());
List<Account> accounts = new ArrayList<>();
for (Entry<Account.Type, JCheckBox> entry : accountTypeMap.entrySet()) {
if (entry.getValue().isSelected()) {
accounts.addAll(communicationsManager.getAccounts(entry.getKey()));
}
}
em.setRootContext(new AbstractNode(new AccountsNodeChildren(accounts)));
//TODO: uncomment and correct this one AccountTypeFilter is in place
//commsFilter.addAndFilter(getAccountTypeFilter());
final CommunicationsManager communicationsManager = Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager();
accountDeviceInstances.addAll(communicationsManager.getAccountDeviceInstancesWithRelationships(commsFilter));
em.setRootContext(new AbstractNode(new AccountsDeviceInstanceChildren(accountDeviceInstances)));
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "There was a error loading the accounts.", ex);
}
}//GEN-LAST:event_applyFiltersButtonActionPerformed
private DeviceFilter getDevceFilter() {
DeviceFilter deviceFilter = new DeviceFilter(devicesMap.entrySet().stream()
.filter(entry -> entry.getValue().isSelected())
.map(entry -> entry.getKey().getDeviceId()).collect(Collectors.toSet()));
return deviceFilter;
}
//TODO: uncomment and correct this one AccountTypeFilter is in place
//private AccountTypeFilter getAccountTypeFilter() {
// AccountTypeFilter accountTypeFilter = new AccountTypeFilter(accountTypeMap.entrySet().stream()
// .filter(entry -> entry.getValue().isSelected())
// .map(entry -> entry.getKey()).collect(Collectors.toSet()));
// return accountTypeFilter;
//}
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
private void setAllTypesSelected(boolean selected) {
setAllSelected(accountTypeMap, selected);

View File

@ -222,9 +222,6 @@ class QueryResults {
* Post an artifact for the hit to the blackboard.
*/
BlackboardArtifact artifact = query.postKeywordHitToBlackboard(content, keyword, hit, snippet, query.getKeywordList().getName());
if (null == artifact) {
logger.log(Level.SEVERE, "Error posting keyword hit artifact for keyword {0} in {1} to the blackboard", new Object[]{keyword.toString(), content}); //NON-NLS
}
/*
* Send an ingest inbox message for the hit.