Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
HostNode.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 */
19package org.sleuthkit.autopsy.datamodel;
20
21import java.beans.PropertyChangeEvent;
22import java.beans.PropertyChangeListener;
23import java.util.ArrayList;
24import java.util.EnumSet;
25import java.util.List;
26import java.util.Optional;
27import java.util.function.Function;
28import java.util.logging.Level;
29import java.util.stream.Collectors;
30import javax.swing.Action;
31import org.openide.nodes.ChildFactory;
32
33import org.openide.nodes.Children;
34import org.openide.nodes.Node;
35import org.openide.nodes.Sheet;
36import org.openide.util.NbBundle;
37import org.openide.util.NbBundle.Messages;
38import org.openide.util.WeakListeners;
39import org.openide.util.lookup.Lookups;
40import org.sleuthkit.autopsy.casemodule.Case;
41import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
42import org.sleuthkit.autopsy.casemodule.events.HostsUpdatedEvent;
43import org.sleuthkit.autopsy.coreutils.Logger;
44import org.sleuthkit.autopsy.datamodel.hosts.AssociatePersonsMenuAction;
45import org.sleuthkit.autopsy.datamodel.hosts.MergeHostMenuAction;
46import org.sleuthkit.autopsy.datamodel.hosts.RemoveParentPersonAction;
47import org.sleuthkit.datamodel.DataSource;
48import org.sleuthkit.datamodel.Host;
49import org.sleuthkit.datamodel.Person;
50import org.sleuthkit.datamodel.SleuthkitVisitableItem;
51import org.sleuthkit.datamodel.TskCoreException;
52
57@NbBundle.Messages(value = {"HostGroupingNode_unknownHostNode_title=Unknown Host"})
58public class HostNode extends DisplayableItemNode {
59
63 private static class HostGroupingChildren extends ChildFactory.Detachable<DataSourceGrouping> {
64
65 private static final Logger logger = Logger.getLogger(HostGroupingChildren.class.getName());
66
67 private final Host host;
68 private final Function<DataSourceGrouping, Node> dataSourceToNode;
69
76 HostGroupingChildren(Function<DataSourceGrouping, Node> dataSourceToNode, Host host) {
77 this.host = host;
78 this.dataSourceToNode = dataSourceToNode;
79 }
80
86 private final PropertyChangeListener dataSourceAddedPcl = new PropertyChangeListener() {
87 @Override
88 public void propertyChange(PropertyChangeEvent evt) {
89 String eventType = evt.getPropertyName();
90 if (eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())
91 || eventType.equals(Case.Events.HOSTS_DELETED.toString())) {
92 refresh(true);
93 }
94 }
95 };
96
97 private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(dataSourceAddedPcl, null);
98
99 @Override
100 protected void addNotify() {
101 super.addNotify();
103 }
104
105 @Override
106 protected void finalize() throws Throwable {
107 super.finalize();
109 }
110
111 @Override
113 return this.dataSourceToNode.apply(key);
114 }
115
116 @Override
117 protected boolean createKeys(List<DataSourceGrouping> toPopulate) {
118 List<DataSource> dataSources = null;
119 try {
120 dataSources = Case.getCurrentCaseThrows().getSleuthkitCase().getHostManager().getDataSourcesForHost(host);
121 } catch (NoCurrentCaseException | TskCoreException ex) {
122 String hostName = host == null || host.getName() == null ? "<unknown>" : host.getName();
123 logger.log(Level.WARNING, String.format("Unable to get data sources for host: %s", hostName), ex);
124 }
125
126 if (dataSources != null) {
127 toPopulate.addAll(dataSources.stream()
128 .filter(ds -> ds != null)
129 .map(DataSourceGrouping::new)
130 .sorted((a, b) -> getNameOrEmpty(a).compareToIgnoreCase(getNameOrEmpty(b)))
131 .collect(Collectors.toList()));
132 }
133
134 return true;
135 }
136
144 private String getNameOrEmpty(DataSourceGrouping dsGroup) {
145 return (dsGroup == null || dsGroup.getDataSource() == null || dsGroup.getDataSource().getName() == null)
146 ? ""
147 : dsGroup.getDataSource().getName();
148 }
149 }
150
151 private static final Logger logger = Logger.getLogger(HostNode.class.getName());
152 private static final String ICON_PATH = "org/sleuthkit/autopsy/images/host.png";
154
159 private static final Function<DataSourceGrouping, Node> HOST_DATA_SOURCES = key -> {
160 if (key.getDataSource() instanceof SleuthkitVisitableItem) {
161 return ((SleuthkitVisitableItem) key.getDataSource()).accept(CREATE_TSK_NODE_VISITOR);
162 } else {
163 return null;
164 }
165 };
166
170 private static final Function<DataSourceGrouping, Node> HOST_GROUPING_CONVERTER = key -> {
171 if (key == null || key.getDataSource() == null) {
172 return null;
173 }
174
175 return new DataSourceGroupingNode(key.getDataSource());
176 };
177
181 private final PropertyChangeListener hostChangePcl = new PropertyChangeListener() {
182 @Override
183 public void propertyChange(PropertyChangeEvent evt) {
184 String eventType = evt.getPropertyName();
185 if (hostId != null && eventType.equals(Case.Events.HOSTS_UPDATED.toString()) && evt instanceof HostsUpdatedEvent) {
186 ((HostsUpdatedEvent) evt).getHosts().stream()
187 .filter(h -> h != null && h.getHostId() == hostId)
188 .findFirst()
189 .ifPresent((newHost) -> {
190 setName(newHost.getName());
191 setDisplayName(newHost.getName());
192 });
193 }
194 }
195 };
196
197 private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(hostChangePcl, null);
198
199 /*
200 * Get the host name or 'unknown host' if null.
201 *
202 * @param host The host.
203 * @return The display name.
204 */
205 private static String getHostName(Host host) {
206 return (host == null || host.getName() == null)
207 ? Bundle.HostGroupingNode_unknownHostNode_title()
208 : host.getName();
209 }
210
211 private final Host host;
212 private final Long hostId;
213
220 HostNode(HostDataSources hosts) {
221 this(Children.create(new HostGroupingChildren(HOST_DATA_SOURCES, hosts.getHost()), true), hosts.getHost());
222 }
223
230 HostNode(HostGrouping hostGrouping) {
231 this(Children.create(new HostGroupingChildren(HOST_GROUPING_CONVERTER, hostGrouping.getHost()), true), hostGrouping.getHost());
232 }
233
240 private HostNode(Children children, Host host) {
241 this(children, host, getHostName(host));
242 }
243
251 private HostNode(Children children, Host host, String displayName) {
252 super(children,
253 host == null ? Lookups.fixed(displayName) : Lookups.fixed(host, displayName));
254
255 hostId = host == null ? null : host.getHostId();
257 super.setName(displayName);
258 super.setDisplayName(displayName);
259 this.setIconBaseWithExtension(ICON_PATH);
260 this.host = host;
261 }
262
263 @Override
264 public boolean isLeafTypeNode() {
265 return false;
266 }
267
268 @Override
269 public String getItemType() {
270 return getClass().getName();
271 }
272
273 @Override
274 public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
275 return visitor.visit(this);
276 }
277
278 @Messages({
279 "HostNode_createSheet_nameProperty=Name",})
280 @Override
281 protected Sheet createSheet() {
282 Sheet sheet = Sheet.createDefault();
283 Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
284 if (sheetSet == null) {
285 sheetSet = Sheet.createPropertiesSet();
286 sheet.put(sheetSet);
287 }
288
289 sheetSet.put(new NodeProperty<>("Name", Bundle.HostNode_createSheet_nameProperty(), "", getDisplayName())); //NON-NLS
290
291 return sheet;
292 }
293
294 @Override
295 @Messages({"HostNode_actions_associateWithExisting=Associate with existing person...",
296 "HostNode_actions_associateWithNew=Associate with new person...",
297 "# {0} - hostName",
298 "HostNode_actions_removeFromPerson=Remove from person ({0})"})
299 public Action[] getActions(boolean context) {
300
301 List<Action> actionsList = new ArrayList<>();
302
303 // if there is a host, then provide actions
304 if (this.host != null) {
305
306 // Add the appropriate Person action
307 Optional<Person> parent;
308 try {
309 parent = Case.getCurrentCaseThrows().getSleuthkitCase().getPersonManager().getPerson(this.host);
310 } catch (NoCurrentCaseException | TskCoreException ex) {
311 logger.log(Level.WARNING, String.format("Error fetching parent person of host: %s", this.host.getName() == null ? "<null>" : this.host.getName()), ex);
312 return new Action[0];
313 }
314
315 // if there is a parent, only give option to remove parent person.
316 if (parent.isPresent()) {
317 actionsList.add(new RemoveParentPersonAction(this.host, parent.get()));
318 } else {
319 actionsList.add(new AssociatePersonsMenuAction(this.host));
320 }
321
322 // Add option to merge hosts
323 actionsList.add(new MergeHostMenuAction(this.host));
324 }
325 return actionsList.toArray(new Action[actionsList.size()]);
326 }
327}
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition Case.java:757
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition Case.java:712
synchronized static Logger getLogger(String name)
Definition Logger.java:124
boolean createKeys(List< DataSourceGrouping > toPopulate)
final Function< DataSourceGrouping, Node > dataSourceToNode
Definition HostNode.java:68
final PropertyChangeListener weakPcl
Action[] getActions(boolean context)
final PropertyChangeListener hostChangePcl
HostNode(Children children, Host host)
static final Function< DataSourceGrouping, Node > HOST_GROUPING_CONVERTER
static final Function< DataSourceGrouping, Node > HOST_DATA_SOURCES
static final CreateSleuthkitNodeVisitor CREATE_TSK_NODE_VISITOR
HostNode(Children children, Host host, String displayName)
static String getHostName(Host host)

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.