This commit is contained in:
Greg DiCristofaro
2021-02-04 12:14:43 -05:00
parent e3f9fcd9c0
commit 2952637fbf
5 changed files with 105 additions and 118 deletions
@@ -90,20 +90,19 @@ public final class AutopsyTreeChildFactory extends ChildFactory.Detachable<Objec
if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) {
// TODO replace with sleuthkit call when PersonManager created
PersonManager personManager = new PersonManager();
HostManager hostManager = tskCase.getHostManager();
Set<Person> persons = personManager.getPersons();
if (!CollectionUtils.isEmpty(persons)) {
persons.stream()
.sorted((a, b) -> compare(Person::getName, a, b))
.map(p -> new PersonGrouping(personManager, hostManager, p))
.map(PersonGrouping::new)
.sorted()
.forEach(list::add);
return true;
} else {
Set<Host> hosts = tskCase.getHostManager().getHosts();
hosts.stream()
.sorted((a, b) -> compare(Host::getName, a, b))
.map(h -> new HostGrouping(hostManager, h))
.map(HostGrouping::new)
.sorted()
.forEach(list::add);
return true;
}
@@ -150,20 +149,4 @@ public final class AutopsyTreeChildFactory extends ChildFactory.Detachable<Objec
public void refreshChildren() {
refresh(true);
}
private <T> int compare(Function<T, String> keyFunction, T objA, T objB) {
String thisKey = objA == null ? null : keyFunction.apply(objA);
String otherKey = objB == null ? null : keyFunction.apply(objB);
// push unknown host to bottom
if (thisKey == null && otherKey == null) {
return 0;
} else if (thisKey == null) {
return 1;
} else if (otherKey == null) {
return -1;
}
return thisKey.compareToIgnoreCase(otherKey);
}
}
@@ -20,33 +20,21 @@ package org.sleuthkit.autopsy.datamodel;
import java.util.Objects;
import org.sleuthkit.datamodel.Host;
import org.sleuthkit.datamodel.HostManager;
/**
* A top level UI grouping of data sources under a host.
*/
public class HostGrouping implements AutopsyVisitableItem {
public class HostGrouping implements AutopsyVisitableItem, Comparable<HostGrouping> {
private final Host host;
private final HostManager hostManager;
/**
* Main constructor.
*
* @param hostManager The host manager from which to gather information
* about the host.
* @param host The host record.
*/
HostGrouping(HostManager hostManager, Host host) {
HostGrouping(Host host) {
this.host = host;
this.hostManager = hostManager;
}
/**
* @return The host manager from which to gather information about the host.
*/
HostManager getHostManager() {
return hostManager;
}
/**
@@ -83,4 +71,25 @@ public class HostGrouping implements AutopsyVisitableItem {
return thisId == otherId;
}
/*
* Compares two host groupings to be displayed in a list of children under
* the person.
*/
@Override
public int compareTo(HostGrouping o) {
String thisHost = this.getHost() == null ? null : this.getHost().getName();
String otherHost = o == null || o.getHost() == null ? null : o.getHost().getName();
// push unknown host to bottom
if (thisHost == null && otherHost == null) {
return 0;
} else if (thisHost == null) {
return 1;
} else if (otherHost == null) {
return -1;
}
return thisHost.compareToIgnoreCase(otherHost);
}
}
@@ -24,16 +24,17 @@ import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import org.apache.commons.lang3.StringUtils;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children;
import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.Host;
import org.sleuthkit.datamodel.HostManager;
import org.sleuthkit.datamodel.TskCoreException;
/**
@@ -46,23 +47,19 @@ class HostGroupingNode extends DisplayableItemNode {
/**
* Provides the data source children for this host.
*/
private static class HostChildren extends ChildFactory.Detachable<DataSource> {
private static class HostChildren extends ChildFactory.Detachable<DataSourceGrouping> {
private static final Logger logger = Logger.getLogger(HostChildren.class.getName());
private final Host host;
private final HostManager hostManager;
/**
* Main constructor.
*
* @param hostManager The host manager to use to fetch data concerning
* the host.
* @param host The host.
*/
HostChildren(HostManager hostManager, Host host) {
HostChildren(Host host) {
this.host = host;
this.hostManager = hostManager;
}
/**
@@ -73,8 +70,7 @@ class HostGroupingNode extends DisplayableItemNode {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String eventType = evt.getPropertyName();
if (eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())
|| eventType.equals(Case.Events.DATA_SOURCE_DELETED.toString())) {
if (eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
refresh(true);
}
}
@@ -82,37 +78,39 @@ class HostGroupingNode extends DisplayableItemNode {
@Override
protected void addNotify() {
super.addNotify();
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.DATA_SOURCE_DELETED), pcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED), pcl);
}
@Override
protected void removeNotify() {
super.removeNotify();
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.DATA_SOURCE_DELETED), pcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED), pcl);
}
@Override
protected boolean createKeys(List<DataSource> toPopulate) {
protected DataSourceGroupingNode createNodeForKey(DataSourceGrouping key) {
return (key == null || key.getDataSource() == null) ? null : new DataSourceGroupingNode(key.getDataSource());
}
@Override
protected boolean createKeys(List<DataSourceGrouping> toPopulate) {
Set<DataSource> dataSources = null;
try {
dataSources = this.hostManager.getDataSourcesForHost(host);
} catch (TskCoreException ex) {
dataSources = Case.getCurrentCaseThrows().getSleuthkitCase().getHostManager().getDataSourcesForHost(host);
} catch (NoCurrentCaseException | TskCoreException ex) {
String hostName = host == null || host.getName() == null ? "<unknown>" : host.getName();
logger.log(Level.WARNING, String.format("Unable to get data sources for host: %s", hostName), ex);
}
if (dataSources != null) {
toPopulate.addAll(dataSources);
dataSources.stream()
.filter(ds -> ds != null)
.map(DataSourceGrouping::new)
.sorted((a, b) -> StringUtils.compareIgnoreCase(a.getDataSource().getName(), b.getDataSource().getName()))
.forEach(toPopulate::add);
}
return true;
}
@Override
protected DataSourceGroupingNode createNodeForKey(DataSource key) {
return key == null ? null : new DataSourceGroupingNode(key);
}
}
private static final String ICON_PATH = "org/sleuthkit/autopsy/images/host.png";
@@ -120,12 +118,10 @@ class HostGroupingNode extends DisplayableItemNode {
/**
* Main constructor.
*
* @param hostManager The pertinent host manager to retrieve more
* information about the host.
* @param host The host.
*/
HostGroupingNode(HostManager hostManager, Host host) {
super(Children.create(new HostChildren(hostManager, host), false), host == null ? null : Lookups.singleton(host));
HostGroupingNode(Host host) {
super(Children.create(new HostChildren(host), false), host == null ? null : Lookups.singleton(host));
String safeName = (host == null || host.getName() == null)
? Bundle.HostNode_unknownHostNode_title()
@@ -20,43 +20,23 @@ package org.sleuthkit.autopsy.datamodel;
import java.util.Objects;
import org.sleuthkit.autopsy.datamodel.PersonGroupingNode.Person;
import org.sleuthkit.autopsy.datamodel.PersonGroupingNode.PersonManager;
import org.sleuthkit.datamodel.HostManager;
/**
* A top level UI grouping of hosts under a person.
*/
public class PersonGrouping implements AutopsyVisitableItem {
public class PersonGrouping implements AutopsyVisitableItem, Comparable<PersonGrouping> {
private final PersonManager personManager;
private final HostManager hostManager;
private final Person person;
/**
* Main constructor.
* @param personManager The person manager for the case.
* @param hostManager The host manager for the case.
*
* @param person The person to be represented.
*/
PersonGrouping(PersonManager personManager, HostManager hostManager, Person person) {
this.personManager = personManager;
this.hostManager = hostManager;
PersonGrouping(Person person) {
this.person = person;
}
/**
* @return The person manager for the case.
*/
PersonManager getPersonManager() {
return personManager;
}
/**
* @return The host manager for the case.
*/
HostManager getHostManager() {
return hostManager;
}
/**
* @return The person to be represented.
@@ -92,4 +72,25 @@ public class PersonGrouping implements AutopsyVisitableItem {
return thisId == otherId;
}
/*
* Compares two person groupings to be displayed in a list of children under
* the root of the tree.
*/
@Override
public int compareTo(PersonGrouping o) {
String thisPerson = this.getPerson() == null ? null : this.getPerson().getName();
String otherPerson = o == null || o.getPerson() == null ? null : o.getPerson().getName();
// push unknown host to bottom
if (thisPerson == null && otherPerson == null) {
return 0;
} else if (thisPerson == null) {
return 1;
} else if (otherPerson == null) {
return -1;
}
return thisPerson.compareToIgnoreCase(otherPerson);
}
}
@@ -32,17 +32,18 @@ import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.Host;
import org.sleuthkit.datamodel.HostManager;
import org.sleuthkit.datamodel.TskCoreException;
/**
* A node to be displayed in the UI tree for a person and persons grouped in
* this host.
*/
@NbBundle.Messages(value = {"PersonNode_unknownHostNode_title=Unknown Persons"})
@NbBundle.Messages(value = {"PersonNode_unknownPersonNode_title=Unknown Persons"})
class PersonGroupingNode extends DisplayableItemNode {
// stub class until this goes into TSK datamodel.
static class PersonManager {
static class PersonManager {
Set<Person> getPersons() throws TskCoreException {
return Collections.emptySet();
}
@@ -51,7 +52,7 @@ class PersonGroupingNode extends DisplayableItemNode {
return Collections.emptySet();
}
}
// stub class until this goes into TSK datamodel.
static class Person {
@@ -77,28 +78,24 @@ class PersonGroupingNode extends DisplayableItemNode {
/**
* Responsible for creating the host children of this person.
*/
private static class PersonChildren extends ChildFactory.Detachable<Host> {
private static class PersonChildren extends ChildFactory.Detachable<HostGrouping> {
private static final Logger logger = Logger.getLogger(PersonChildren.class.getName());
private final Person person;
private final PersonManager personManager;
private final HostManager hostManager;
/**
* Main constructor.
* @param personManager The person manager for the case.
* @param hostManager The host manager for the case.
*
* @param person The person record.
*/
PersonChildren(PersonManager personManager, HostManager hostManager, Person person) {
PersonChildren(Person person) {
this.person = person;
this.personManager = personManager;
this.hostManager = hostManager;
}
/**
* Listener for handling DATA_SOURCE_ADDED and DATA_SOURCE_DELETED events.
* Listener for handling DATA_SOURCE_ADDED and DATA_SOURCE_DELETED
* events.
*/
private final PropertyChangeListener pcl = new PropertyChangeListener() {
@Override
@@ -113,51 +110,52 @@ class PersonGroupingNode extends DisplayableItemNode {
@Override
protected void addNotify() {
super.addNotify();
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.DATA_SOURCE_DELETED), pcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED), pcl);
}
@Override
protected void removeNotify() {
super.removeNotify();
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.DATA_SOURCE_DELETED), pcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED), pcl);
}
@Override
protected boolean createKeys(List<Host> toPopulate) {
protected HostGroupingNode createNodeForKey(HostGrouping key) {
return key == null ? null : new HostGroupingNode(key.getHost());
}
@Override
protected boolean createKeys(List<HostGrouping> toPopulate) {
Set<Host> hosts = null;
try {
hosts = this.personManager.getHostsForPerson(person);
hosts = new PersonManager().getHostsForPerson(person);
// NOTE: This code will be used when person manager exists
// hosts = Case.getCurrentCaseThrows().getSleuthkitCase().getPersonManager().getHostsForPerson(person);
} catch (TskCoreException ex) {
String personName = person == null || person.getName() == null ? "<unknown>" : person.getName();
logger.log(Level.WARNING, String.format("Unable to get data sources for host: %s", personName), ex);
}
if (hosts != null) {
toPopulate.addAll(hosts);
hosts.stream()
.map(HostGrouping::new)
.sorted()
.forEach(toPopulate::add);
}
return true;
}
@Override
protected HostGroupingNode createNodeForKey(Host key) {
return key == null ? null : new HostGroupingNode(hostManager, key);
}
}
/**
* Main constructor.
* @param personManager The person manager for the case.
* @param hostManager The host manager for the case.
*
* @param person The person record to be represented.
*/
PersonGroupingNode(PersonManager personManager, HostManager hostManager, Person person) {
super(Children.create(new PersonChildren(personManager, hostManager, person), false), person == null ? null : Lookups.singleton(person));
PersonGroupingNode(Person person) {
super(Children.create(new PersonChildren(person), false), person == null ? null : Lookups.singleton(person));
String safeName = (person == null || person.getName() == null)
? Bundle.HostNode_unknownHostNode_title()
? Bundle.PersonNode_unknownPersonNode_title()
: person.getName();
super.setName(safeName);