Autopsy  4.21.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
PersonNode.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2021 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.datamodel;
20 
21 import java.beans.PropertyChangeEvent;
22 import java.beans.PropertyChangeListener;
23 import java.util.Collections;
24 import java.util.EnumSet;
25 import java.util.List;
26 import java.util.Set;
27 import java.util.logging.Level;
28 import java.util.stream.Collectors;
29 import javax.swing.Action;
30 import org.openide.nodes.ChildFactory;
31 import org.openide.nodes.Children;
32 import org.openide.nodes.Sheet;
33 import org.openide.util.NbBundle;
34 import org.openide.util.NbBundle.Messages;
35 import org.openide.util.WeakListeners;
36 import org.openide.util.lookup.Lookups;
43 import org.sleuthkit.datamodel.Host;
44 import org.sleuthkit.datamodel.Person;
45 import org.sleuthkit.datamodel.TskCoreException;
46 
54 @NbBundle.Messages(value = {"PersonNode_unknownPersonNode_title=Unknown Persons"})
55 public class PersonNode extends DisplayableItemNode {
56 
57  private static final String ICON_PATH = "org/sleuthkit/autopsy/images/person.png";
58 
65  public static String getUnknownPersonId() {
66  return Bundle.PersonNode_unknownPersonNode_title();
67  }
68 
72  private static class PersonChildren extends ChildFactory.Detachable<HostGrouping> {
73 
74  private static final Logger logger = Logger.getLogger(PersonChildren.class.getName());
75 
76  private static final Set<Case.Events> HOST_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.HOSTS_ADDED,
81 
82  private static final Set<String> HOST_EVENTS_OF_INTEREST_NAMES = HOST_EVENTS_OF_INTEREST.stream()
83  .map(ev -> ev.name())
84  .collect(Collectors.toSet());
85 
86  private final Person person;
87 
93  PersonChildren(Person person) {
94  this.person = person;
95 
96  }
97 
106  private final PropertyChangeListener hostAddedDeletedPcl = new PropertyChangeListener() {
107  @Override
108  public void propertyChange(PropertyChangeEvent evt) {
109  String eventType = evt.getPropertyName();
110  if (eventType != null && HOST_EVENTS_OF_INTEREST_NAMES.contains(eventType)) {
111  refresh(true);
112  }
113  }
114  };
115 
116  private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(hostAddedDeletedPcl, null);
117 
118  @Override
119  protected void addNotify() {
120  Case.addEventTypeSubscriber(HOST_EVENTS_OF_INTEREST, weakPcl);
121  }
122 
123  @Override
124  protected void finalize() throws Throwable {
125  super.finalize();
126  Case.removeEventTypeSubscriber(HOST_EVENTS_OF_INTEREST, weakPcl);
127  }
128 
129  @Override
131  return key == null ? null : new HostNode(key);
132  }
133 
134  @Override
135  protected boolean createKeys(List<HostGrouping> toPopulate) {
136  List<Host> hosts = Collections.emptyList();
137  try {
138  if (person != null) {
139  hosts = Case.getCurrentCaseThrows().getSleuthkitCase().getPersonManager().getHostsForPerson(person);
140  } else {
141  // This is the "Unknown Persons" node, get the hosts that are not associated with a person.
142  hosts = Case.getCurrentCaseThrows().getSleuthkitCase().getPersonManager().getHostsWithoutPersons();
143  }
144  } catch (NoCurrentCaseException | TskCoreException ex) {
145  String personName = person == null || person.getName() == null ? "<unknown>" : person.getName();
146  logger.log(Level.WARNING, String.format("Unable to get data sources for host: %s", personName), ex);
147  }
148 
149  toPopulate.addAll(hosts.stream()
150  .map(HostGrouping::new)
151  .sorted()
152  .collect(Collectors.toList()));
153 
154  return true;
155  }
156  }
157 
158  private final Person person;
159  private final Long personId;
160 
165  private final PropertyChangeListener personChangePcl = new PropertyChangeListener() {
166  @Override
167  public void propertyChange(PropertyChangeEvent evt) {
168  String eventType = evt.getPropertyName();
169  if (personId != null && eventType.equals(Case.Events.PERSONS_UPDATED.toString()) && evt instanceof PersonsUpdatedEvent) {
170  ((PersonsUpdatedEvent) evt).getNewValue().stream()
171  .filter(p -> p != null && p.getPersonId() == personId)
172  .findFirst()
173  .ifPresent((newPerson) -> {
174  setName(newPerson.getName());
175  setDisplayName(newPerson.getName());
176  });
177  }
178  }
179  };
180 
181  private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(personChangePcl, null);
182 
190  private static String getDisplayName(Person person) {
191  return (person == null || person.getName() == null)
192  ? getUnknownPersonId()
193  : person.getName();
194  }
195 
201  PersonNode(Person person) {
202  this(person, getDisplayName(person));
203  }
204 
211  private PersonNode(Person person, String displayName) {
212  super(Children.create(new PersonChildren(person), true),
213  person == null ? Lookups.fixed(displayName) : Lookups.fixed(person, displayName));
214  super.setName(displayName);
215  super.setDisplayName(displayName);
216  this.setIconBaseWithExtension(ICON_PATH);
217  this.person = person;
218  this.personId = person == null ? null : person.getPersonId();
219  Case.addEventTypeSubscriber(EnumSet.of(Case.Events.PERSONS_UPDATED), weakPcl);
220  }
221 
222  @Override
223  public boolean isLeafTypeNode() {
224  return false;
225  }
226 
227  @Override
228  public String getItemType() {
229  return getClass().getName();
230  }
231 
232  @Override
233  public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
234  return visitor.visit(this);
235  }
236 
237  @NbBundle.Messages({
238  "PersonGroupingNode_createSheet_nameProperty=Name",})
239  @Override
240  protected Sheet createSheet() {
241  Sheet sheet = Sheet.createDefault();
242  Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
243  if (sheetSet == null) {
244  sheetSet = Sheet.createPropertiesSet();
245  sheet.put(sheetSet);
246  }
247 
248  sheetSet.put(new NodeProperty<>("Name", Bundle.PersonGroupingNode_createSheet_nameProperty(), "", getDisplayName())); //NON-NLS
249 
250  return sheet;
251  }
252 
253  @Override
254  @Messages({"PersonGroupingNode_actions_rename=Rename Person...",
255  "PersonGroupingNode_actions_delete=Delete Person"})
256  public Action[] getActions(boolean context) {
257  if (this.person == null) {
258  return new Action[0];
259  } else {
260  return new Action[]{
261  new EditPersonAction(this.person),
262  new DeletePersonAction(this.person),
263  null
264  };
265  }
266  }
267 }
static String getDisplayName(Person person)
boolean createKeys(List< HostGrouping > toPopulate)
Action[] getActions(boolean context)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:708
PersonNode(Person person, String displayName)
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:753

Copyright © 2012-2022 Basis Technology. Generated on: Tue Feb 6 2024
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.