Autopsy  4.10.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
ViewContextAction.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2018 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.directorytree;
20 
21 import java.awt.EventQueue;
22 import java.awt.event.ActionEvent;
23 import java.beans.PropertyVetoException;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.List;
27 import java.util.Objects;
28 import java.util.logging.Level;
30 import javax.swing.AbstractAction;
31 import org.openide.nodes.AbstractNode;
32 import org.openide.explorer.ExplorerManager;
33 import org.openide.explorer.view.TreeView;
34 import org.openide.nodes.Children;
35 import org.openide.nodes.Node;
36 import org.openide.util.NbBundle.Messages;
48 import org.sleuthkit.datamodel.AbstractFile;
49 import org.sleuthkit.datamodel.BlackboardArtifact;
50 import org.sleuthkit.datamodel.Content;
51 import org.sleuthkit.datamodel.ContentVisitor;
52 import org.sleuthkit.datamodel.DataSource;
53 import org.sleuthkit.datamodel.FileSystem;
54 import org.sleuthkit.datamodel.SleuthkitCase;
55 import org.sleuthkit.datamodel.TskCoreException;
56 import org.sleuthkit.datamodel.TskData;
57 import org.sleuthkit.datamodel.TskDataException;
58 import org.sleuthkit.datamodel.VolumeSystem;
59 
66 public class ViewContextAction extends AbstractAction {
67 
68  private static final long serialVersionUID = 1L;
69  private static final Logger logger = Logger.getLogger(ViewContextAction.class.getName());
70  private final Content content;
71 
81  public ViewContextAction(String displayName, BlackboardArtifactNode artifactNode) {
82  super(displayName);
83  this.content = artifactNode.getLookup().lookup(Content.class);
84  if (this.content != null && this.content instanceof AbstractFile) {
85  AbstractFile file = (AbstractFile) content;
86  //disable the action if the content is a file and the file is hidden
87  if ((TskData.FileKnown.KNOWN == file.getKnown() && UserPreferences.hideKnownFilesInDataSourcesTree())
88  || (TskData.TSK_DB_FILES_TYPE_ENUM.SLACK == file.getType() && UserPreferences.hideSlackFilesInDataSourcesTree())) {
89  this.setEnabled(false);
90  }
91  }
92  }
93 
104  public ViewContextAction(String displayName, AbstractFsContentNode<? extends AbstractFile> fileSystemContentNode) {
105  super(displayName);
106  this.content = fileSystemContentNode.getLookup().lookup(Content.class);
107  }
108 
118  public ViewContextAction(String displayName, Content content) {
119  super(displayName);
120  this.content = content;
121  }
122 
131  @Override
132  @Messages({
133  "ViewContextAction.errorMessage.cannotFindDirectory=Failed to locate directory.",
134  "ViewContextAction.errorMessage.cannotSelectDirectory=Failed to select directory in tree.",
135  "ViewContextAction.errorMessage.cannotFindNode=Failed to locate data source node in tree."
136  })
137  public void actionPerformed(ActionEvent event) {
138  EventQueue.invokeLater(() -> {
139  /*
140  * Get the "Data Sources" node from the tree view.
141  */
143  ExplorerManager treeViewExplorerMgr = treeViewTopComponent.getExplorerManager();
144  Node parentTreeViewNode;
145  if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) { // 'Group by Data Source' view
146 
147  SleuthkitCase skCase;
148  String dsname;
149  try {
150  // get the objid/name of the datasource of the selected content.
152  long contentDSObjid = content.getDataSource().getId();
153  DataSource datasource = skCase.getDataSource(contentDSObjid);
154  dsname = datasource.getName();
155 
156  Children rootChildren = treeViewExplorerMgr.getRootContext().getChildren();
157  Node datasourceGroupingNode = rootChildren.findChild(dsname);
158  if (!Objects.isNull(datasourceGroupingNode)) {
159  Children dsChildren = datasourceGroupingNode.getChildren();
160  parentTreeViewNode = dsChildren.findChild(DataSourcesNode.NAME);
161  } else {
162  MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindNode());
163  logger.log(Level.SEVERE, "Failed to locate data source node in tree."); //NON-NLS
164  return;
165  }
166  } catch (NoCurrentCaseException | TskDataException | TskCoreException ex) {
167  MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindNode());
168  logger.log(Level.SEVERE, "Failed to locate data source node in tree.", ex); //NON-NLS
169  return;
170  }
171  } else { // Classic view
172  // Start the search at the DataSourcesNode
173  parentTreeViewNode = treeViewExplorerMgr.getRootContext().getChildren().findChild(DataSourcesNode.NAME);
174  }
175 
176  /*
177  * Get the parent content for the content to be selected in the
178  * results view. If the parent content is null, then the specified
179  * content is a data source, and the parent tree view node is the
180  * "Data Sources" node. Otherwise, the tree view needs to be
181  * searched to find the parent treeview node.
182  */
183  Content parentContent = null;
184 
185  try {
186  parentContent = content.getParent();
187  } catch (TskCoreException ex) {
188  MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindDirectory());
189  logger.log(Level.SEVERE, String.format("Could not get parent of Content object: %s", content), ex); //NON-NLS
190  return;
191  }
192  if (null != parentContent) {
193  /*
194  * Get an ordered list of the ancestors of the specified
195  * content, starting with its data source.
196  *
197  */
198  AncestorVisitor ancestorVisitor = new AncestorVisitor();
199  List<Content> contentBranch = parentContent.accept(ancestorVisitor);
200  Collections.reverse(contentBranch);
201 
214  Node dummyRootNode = new DirectoryTreeFilterNode(new AbstractNode(new RootContentChildren(contentBranch)), true);
215  Children ancestorChildren = dummyRootNode.getChildren();
216 
217  /*
218  * Search the tree for the parent node. Note that this algorithm
219  * simply discards "extra" ancestor nodes not shown in the tree,
220  * such as the root directory of the file system for file system
221  * content.
222  */
223  Children treeNodeChildren = parentTreeViewNode.getChildren();
224  for (int i = 0; i < ancestorChildren.getNodesCount(); i++) {
225  Node ancestorNode = ancestorChildren.getNodeAt(i);
226  for (int j = 0; j < treeNodeChildren.getNodesCount(); j++) {
227  Node treeNode = treeNodeChildren.getNodeAt(j);
228  if (ancestorNode.getName().equals(treeNode.getName())) {
229  parentTreeViewNode = treeNode;
230  treeNodeChildren = treeNode.getChildren();
231  break;
232  }
233  }
234  }
235  }
236 
237  /*
238  * Set the child selection info of the parent tree node, then select
239  * the parent node in the tree view. The results view will retrieve
240  * this selection info and use it to complete this action when the
241  * tree view top component responds to the selection of the parent
242  * node by pushing it into the results view top component.
243  */
244  DisplayableItemNode undecoratedParentNode = (DisplayableItemNode) ((DirectoryTreeFilterNode) parentTreeViewNode).getOriginal();
245  undecoratedParentNode.setChildNodeSelectionInfo(new ContentNodeSelectionInfo(content));
246  if (content instanceof BlackboardArtifact) {
247  BlackboardArtifact artifact = ((BlackboardArtifact) content);
248  long associatedId = artifact.getObjectID();
249  try {
250  Content associatedFileContent = artifact.getSleuthkitCase().getContentById(associatedId);
251  undecoratedParentNode.setChildNodeSelectionInfo(new ContentNodeSelectionInfo(associatedFileContent));
252  } catch (TskCoreException ex) {
253  logger.log(Level.SEVERE, "Could not find associated content from artifact with id %d", artifact.getId());
254  }
255  }
256 
257  TreeView treeView = treeViewTopComponent.getTree();
258  treeView.expandNode(parentTreeViewNode);
259  if (treeViewTopComponent.getSelectedNode().equals(parentTreeViewNode)) {
260  //In the case where our tree view already has the destination directory selected
261  //due to an optimization in the ExplorerManager.setExploredContextAndSelection method
262  //the property change we listen for to call DirectoryTreeTopComponent.respondSelection
263  //will not be sent so we call it manually ourselves after making
264  //the directory listing the active tab.
265  treeViewTopComponent.setDirectoryListingActive();
266  treeViewTopComponent.respondSelection(treeViewExplorerMgr.getSelectedNodes(), new Node[]{parentTreeViewNode});
267  } else {
268  try {
269  treeViewExplorerMgr.setExploredContextAndSelection(parentTreeViewNode, new Node[]{parentTreeViewNode});
270  } catch (PropertyVetoException ex) {
271  MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotSelectDirectory());
272  logger.log(Level.SEVERE, "Failed to select the parent node in the tree view", ex); //NON-NLS
273  }
274  }
275  });
276  }
277 
283  private static class AncestorVisitor extends ContentVisitor.Default<List<Content>> {
284 
285  List<Content> lineage = new ArrayList<>();
286 
287  @Override
288  protected List<Content> defaultVisit(Content content) {
289  lineage.add(content);
290  Content parent = null;
291  try {
292  parent = content.getParent();
293  } catch (TskCoreException ex) {
294  logger.log(Level.SEVERE, String.format("Could not get parent of Content object: %s", content), ex); //NON-NLS
295  }
296  return parent == null ? lineage : parent.accept(this);
297  }
298 
299  @Override
300  public List<Content> visit(VolumeSystem volumeSystem) {
301  /*
302  * Volume systems are not shown in the tree view. This is not
303  * strictly necesssary given the algorithm above, but it is a simple
304  * optimization.
305  */
306  return skipToParent(volumeSystem);
307  }
308 
309  @Override
310  public List<Content> visit(FileSystem fileSystem) {
311  /*
312  * File systems are not shown in the tree view. This is not strictly
313  * necesssary given the algorithm above, but it is a simple
314  * optimization.
315  */
316  return skipToParent(fileSystem);
317  }
318 
319  private List<Content> skipToParent(Content content) {
320  Content parent = null;
321  try {
322  parent = content.getParent();
323  } catch (TskCoreException ex) {
324  logger.log(Level.SEVERE, String.format("Could not get parent of Content object: %s", content), ex); //NON-NLS
325  }
326  return parent == null ? lineage : parent.accept(this);
327  }
328  }
329 
330 }
ViewContextAction(String displayName, Content content)
ViewContextAction(String displayName, BlackboardArtifactNode artifactNode)
ViewContextAction(String displayName, AbstractFsContentNode<?extends AbstractFile > fileSystemContentNode)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
void setChildNodeSelectionInfo(NodeSelectionInfo selectedChildNodeInfo)
static synchronized DirectoryTreeTopComponent findInstance()

Copyright © 2012-2018 Basis Technology. Generated on: Fri Mar 22 2019
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.