19 package org.sleuthkit.autopsy.directorytree;
 
   21 import java.awt.Cursor;
 
   22 import java.awt.EventQueue;
 
   23 import java.beans.PropertyChangeEvent;
 
   24 import java.beans.PropertyChangeListener;
 
   25 import java.beans.PropertyVetoException;
 
   26 import java.io.IOException;
 
   27 import java.util.ArrayList;
 
   28 import java.util.Arrays;
 
   29 import java.util.Collections;
 
   30 import java.util.EnumSet;
 
   31 import java.util.HashSet;
 
   32 import java.util.LinkedList;
 
   33 import java.util.List;
 
   35 import java.util.Objects;
 
   36 import java.util.Optional;
 
   38 import java.util.concurrent.ExecutionException;
 
   39 import java.util.logging.Level;
 
   40 import java.util.prefs.PreferenceChangeEvent;
 
   41 import java.util.prefs.PreferenceChangeListener;
 
   42 import java.util.stream.Collectors;
 
   43 import java.util.stream.Stream;
 
   44 import javax.swing.Action;
 
   45 import javax.swing.SwingUtilities;
 
   46 import javax.swing.SwingWorker;
 
   47 import javax.swing.event.PopupMenuEvent;
 
   48 import javax.swing.event.PopupMenuListener;
 
   49 import javax.swing.tree.TreeSelectionModel;
 
   50 import org.apache.commons.lang3.StringUtils;
 
   51 import org.openide.explorer.ExplorerManager;
 
   52 import org.openide.explorer.ExplorerUtils;
 
   53 import org.openide.explorer.view.BeanTreeView;
 
   54 import org.openide.nodes.AbstractNode;
 
   55 import org.openide.nodes.Children;
 
   56 import org.openide.nodes.Node;
 
   57 import org.openide.nodes.NodeNotFoundException;
 
   58 import org.openide.nodes.NodeOp;
 
   59 import org.openide.util.NbBundle;
 
   60 import org.openide.util.NbBundle.Messages;
 
   61 import org.openide.windows.TopComponent;
 
   62 import org.openide.windows.WindowManager;
 
  109     "DirectoryTreeTopComponent.resultsView.title=Listing" 
  111 @SuppressWarnings(
"PMD.SingularField") 
 
  114     private final transient ExplorerManager em = 
new ExplorerManager();
 
  120     private static final String PREFERRED_ID = 
"DirectoryTreeTopComponent"; 
 
  126     private static final long DEFAULT_DATASOURCE_GROUPING_THRESHOLD = 5; 
 
  127     private static final String GROUPING_THRESHOLD_NAME = 
"GroupDataSourceThreshold";
 
  128     private static final String SETTINGS_FILE = 
"CasePreferences.properties"; 
 
  132             .collect(Collectors.toSet());
 
  141         getTree().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
 
  144         putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE);
 
  148         subscribeToChangeEvents();
 
  149         associateLookup(ExplorerUtils.createLookup(em, getActionMap()));
 
  152         this.backList = 
new LinkedList<>();
 
  153         this.forwardList = 
new LinkedList<>();
 
  154         backButton.setEnabled(
false);
 
  155         forwardButton.setEnabled(
false);
 
  157         viewPreferencesPopupMenu.add(viewPreferencesPanel);
 
  158         viewPreferencesPopupMenu.setSize(viewPreferencesPanel.getPreferredSize().width + 6, viewPreferencesPanel.getPreferredSize().height + 6);
 
  159         viewPreferencesPopupMenu.addPopupMenuListener(
new PopupMenuListener() {
 
  161             public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
 
  162                 openViewPreferencesButton.setSelected(
true);
 
  166             public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
 
  167                 openViewPreferencesButton.setSelected(
false);
 
  171             public void popupMenuCanceled(PopupMenuEvent e) {
 
  172                 openViewPreferencesButton.setSelected(
false);
 
  184         BeanTreeView tree = getTree();
 
  187         Node[] rootChildrenNodes = rootChildren.getNodes(
true);
 
  188         if (rootChildrenNodes == null || rootChildrenNodes.length < 1) {
 
  194             Stream.of(rootChildrenNodes)
 
  195                     .flatMap((n) -> getHostNodesAndParents(n).stream())
 
  196                     .filter((n) -> n != null)
 
  197                     .forEach(tree::expandNode);
 
  199             Stream.of(rootChildrenNodes)
 
  200                     .filter(n -> n != null && NODES_TO_EXPAND.contains(n.getName()))
 
  201                     .forEach(tree::expandNode);
 
  215             return Collections.emptyList();
 
  216         } 
else if (node.getLookup().lookup(
Person.class) != null
 
  218             Children children = node.getChildren();
 
  219             Node[] childNodes = children == null ? null : children.getNodes();
 
  220             if (childNodes != null) {
 
  221                 return Stream.of(childNodes)
 
  222                         .flatMap((n) -> Stream.concat(Stream.of(n), getHostNodesAndParents(n).stream()))
 
  223                         .collect(Collectors.toList());
 
  225         } 
else if (node.getLookup().lookup(
Host.class) != null) {
 
  226             return Arrays.asList(node);
 
  228         return Collections.emptyList();
 
  237             public void preferenceChange(PreferenceChangeEvent evt) {
 
  238                 switch (evt.getKey()) {
 
  247                         refreshContentTreeSafe();
 
  255                         refreshContentTreeSafe();
 
  262         this.em.addPropertyChangeListener(
this);
 
  266         this.dataResult.requestActive();
 
  270         this.dataResult.
open();
 
  274         return this.dataResult;
 
  283         return showRejectedResults;
 
  293         this.showRejectedResults = showRejectedResults;
 
  294         if (accounts != null) {
 
  307         viewPreferencesPopupMenu = 
new javax.swing.JPopupMenu();
 
  308         treeView = 
new ExpansionBeanTreeView();
 
  309         backButton = 
new javax.swing.JButton();
 
  310         forwardButton = 
new javax.swing.JButton();
 
  311         openViewPreferencesButton = 
new javax.swing.JButton();
 
  313         treeView.setBorder(null);
 
  315         backButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_back.png"))); 
 
  316         org.openide.awt.Mnemonics.setLocalizedText(backButton, 
org.openide.util.NbBundle.getMessage(
DirectoryTreeTopComponent.class, 
"DirectoryTreeTopComponent.backButton.text")); 
 
  317         backButton.setBorderPainted(
false);
 
  318         backButton.setContentAreaFilled(
false);
 
  319         backButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_back_disabled.png"))); 
 
  320         backButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
 
  321         backButton.setMaximumSize(
new java.awt.Dimension(55, 100));
 
  322         backButton.setMinimumSize(
new java.awt.Dimension(5, 5));
 
  323         backButton.setPreferredSize(
new java.awt.Dimension(24, 24));
 
  324         backButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_back_hover.png"))); 
 
  325         backButton.addActionListener(
new java.awt.event.ActionListener() {
 
  326             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  327                 backButtonActionPerformed(evt);
 
  331         forwardButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_forward.png"))); 
 
  332         org.openide.awt.Mnemonics.setLocalizedText(forwardButton, 
org.openide.util.NbBundle.getMessage(
DirectoryTreeTopComponent.class, 
"DirectoryTreeTopComponent.forwardButton.text")); 
 
  333         forwardButton.setBorderPainted(
false);
 
  334         forwardButton.setContentAreaFilled(
false);
 
  335         forwardButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_forward_disabled.png"))); 
 
  336         forwardButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
 
  337         forwardButton.setMaximumSize(
new java.awt.Dimension(55, 100));
 
  338         forwardButton.setMinimumSize(
new java.awt.Dimension(5, 5));
 
  339         forwardButton.setPreferredSize(
new java.awt.Dimension(24, 24));
 
  340         forwardButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_forward_hover.png"))); 
 
  341         forwardButton.addActionListener(
new java.awt.event.ActionListener() {
 
  342             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  343                 forwardButtonActionPerformed(evt);
 
  347         openViewPreferencesButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/view-preferences-23.png"))); 
 
  348         org.openide.awt.Mnemonics.setLocalizedText(openViewPreferencesButton, 
org.openide.util.NbBundle.getMessage(
DirectoryTreeTopComponent.class, 
"DirectoryTreeTopComponent.openViewPreferencesButton.text")); 
 
  349         openViewPreferencesButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
 
  350         openViewPreferencesButton.setBorderPainted(
false);
 
  351         openViewPreferencesButton.setContentAreaFilled(
false);
 
  352         openViewPreferencesButton.setMaximumSize(
new java.awt.Dimension(24, 24));
 
  353         openViewPreferencesButton.setMinimumSize(
new java.awt.Dimension(24, 24));
 
  354         openViewPreferencesButton.setPreferredSize(
new java.awt.Dimension(24, 24));
 
  355         openViewPreferencesButton.addActionListener(
new java.awt.event.ActionListener() {
 
  356             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  357                 openViewPreferencesButtonActionPerformed(evt);
 
  361         javax.swing.GroupLayout layout = 
new javax.swing.GroupLayout(
this);
 
  362         this.setLayout(layout);
 
  363         layout.setHorizontalGroup(
 
  364             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  365             .addComponent(treeView)
 
  366             .addGroup(layout.createSequentialGroup()
 
  368                 .addComponent(backButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  369                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  370                 .addComponent(forwardButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  371                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 140, Short.MAX_VALUE)
 
  372                 .addComponent(openViewPreferencesButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  375         layout.setVerticalGroup(
 
  376             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  377             .addGroup(layout.createSequentialGroup()
 
  379                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  380                     .addComponent(openViewPreferencesButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  381                     .addComponent(backButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  382                     .addComponent(forwardButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  383                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  384                 .addComponent(treeView, javax.swing.GroupLayout.DEFAULT_SIZE, 919, Short.MAX_VALUE))
 
  390         this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
 
  393         String[] currentNodePath = backList.pollLast();
 
  394         forwardList.addLast(currentNodePath);
 
  395         forwardButton.setEnabled(
true);
 
  402         String[] newCurrentNodePath = backList.peekLast();
 
  405         if (backList.size() > 1) {
 
  406             backButton.setEnabled(
true);
 
  408             backButton.setEnabled(
false);
 
  412         setSelectedNode(newCurrentNodePath, null);
 
  414         this.setCursor(null);
 
  419         this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
 
  421         String[] newCurrentNodePath = forwardList.pollLast();
 
  422         if (!forwardList.isEmpty()) {
 
  423             forwardButton.setEnabled(
true);
 
  425             forwardButton.setEnabled(
false);
 
  428         backList.addLast(newCurrentNodePath);
 
  429         backButton.setEnabled(
true);
 
  432         setSelectedNode(newCurrentNodePath, null);
 
  434         this.setCursor(null);
 
  438         viewPreferencesPanel.
load();
 
  439         viewPreferencesPopupMenu.show(openViewPreferencesButton, 0, openViewPreferencesButton.getHeight() - 1);
 
  459         if (instance == null) {
 
  472         WindowManager winManager = WindowManager.
getDefault();
 
  473         TopComponent win = winManager.findTopComponent(PREFERRED_ID);
 
  476                     "Cannot find " + PREFERRED_ID + 
" component. It will not be located properly in the window system."); 
 
  480             return (DirectoryTreeTopComponent) win;
 
  483                 "There seem to be multiple components with the '" + PREFERRED_ID 
 
  484                 + 
"' ID. That is a potential source of errors and unexpected behavior."); 
 
  496         return TopComponent.PERSISTENCE_NEVER;
 
  507             GroupDataSourcesDialog dialog = 
new GroupDataSourcesDialog(dataSourceCount);
 
  509             if (dialog.groupByDataSourceSelected()) {
 
  511                 refreshContentTreeSafe();
 
  525     @NbBundle.Messages({
"# {0} - dataSourceCount",
 
  526         "DirectoryTreeTopComponent.componentOpened.groupDataSources.text=This case contains {0} data sources. Would you like to group by data source for faster loading?",
 
  527         "DirectoryTreeTopComponent.componentOpened.groupDataSources.title=Group by data source?"})
 
  531         this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
 
  532         Case openCase = null;
 
  538         final Case currentCase = openCase;
 
  540         if (!caseHasData(currentCase)) {
 
  541             getTree().setRootVisible(
false); 
 
  546                 Long settingsThreshold = null;
 
  550                     } 
catch (NumberFormatException ex) {
 
  551                         LOGGER.log(Level.SEVERE, 
"Group data sources threshold is not a number", ex);
 
  556                 final long threshold = settingsThreshold == null ? DEFAULT_DATASOURCE_GROUPING_THRESHOLD : settingsThreshold;
 
  558                 new SwingWorker<Integer, Void>() {
 
  560                     protected Integer doInBackground() 
throws Exception {
 
  561                         int dataSourceCount = 0;
 
  565                             LOGGER.log(Level.SEVERE, 
"Error loading data sources", ex);
 
  567                         return dataSourceCount;
 
  571                     protected void done() {
 
  572                         int dataSourceCount = 0;
 
  574                             dataSourceCount = 
get();
 
  575                         } 
catch (ExecutionException | InterruptedException ex) {
 
  576                             LOGGER.log(Level.SEVERE, 
"Error loading data sources and getting count on background thread", ex);
 
  579                                 && dataSourceCount > threshold) {
 
  580                             promptForDataSourceGrouping(dataSourceCount);
 
  588             autopsyTreeChildren = Children.create(autopsyTreeChildFactory, 
true);
 
  589             Node root = 
new AbstractNode(autopsyTreeChildren) {
 
  596                 public Action[] getActions(
boolean popup) {
 
  597                     return new Action[]{};
 
  603                 public Node.Handle getHandle() {
 
  604                     return new Node.Handle() {
 
  606                         public Node getNode() 
throws IOException {
 
  607                             return em.getRootContext();
 
  613             root = 
new DirectoryTreeFilterNode(root, 
true);
 
  615             em.setRootContext(root);
 
  616             em.getRootContext().setName(currentCase.
getName());
 
  617             em.getRootContext().setDisplayName(currentCase.
getName());
 
  618             getTree().setRootVisible(
false); 
 
  622             new SwingWorker<Node[], Void>() {
 
  624                 protected Node[] doInBackground() 
throws Exception {
 
  625                     Children rootChildren = em.getRootContext().getChildren();
 
  626                     preExpandNodes(rootChildren);
 
  636                     if (rootChildren.getNodesCount() > 0) {
 
  637                         return new Node[]{rootChildren.getNodeAt(0)};
 
  643                 protected void done() {
 
  647                     if (!dataResult.isOpened()) {
 
  658                         Node[] selections = 
get();
 
  659                         if (selections != null && selections.length > 0) {
 
  660                             em.setSelectedNodes(selections);
 
  662                     } 
catch (PropertyVetoException ex) {
 
  663                         LOGGER.log(Level.SEVERE, 
"Error setting default selected node.", ex); 
 
  664                     } 
catch (InterruptedException | ExecutionException ex) {
 
  665                         LOGGER.log(Level.SEVERE, 
"Error expanding tree to initial state.", ex); 
 
  683         autopsyTreeChildren = null;
 
  686     void writeProperties(java.util.Properties p) {
 
  689         p.setProperty(
"version", 
"1.0");
 
  693     Object readProperties(java.util.Properties p) {
 
  694         if (instance == null) {
 
  702         String version = p.getProperty(
"version");
 
  725             return caseHasData(openCase) == 
false;
 
  748         return new Action[]{};
 
  759         Node[] selectedNodes = this.getExplorerManager().getSelectedNodes();
 
  760         if (selectedNodes.length > 0) {
 
  761             result = selectedNodes[0];
 
  775             String changed = 
event.getPropertyName();
 
  785                 if (event.getOldValue() != null && 
event.getNewValue() == null) {
 
  787                     SwingUtilities.invokeLater(() -> {
 
  788                         Node emptyNode = 
new AbstractNode(Children.LEAF);
 
  789                         em.setRootContext(emptyNode);
 
  791                 } 
else if (event.getNewValue() != null) {
 
  793                     Case newCase = (
Case) event.getNewValue();
 
  794                     final String newCaseName = newCase.
getName();
 
  795                     SwingUtilities.invokeLater(() -> {
 
  796                         em.getRootContext().setName(newCaseName);
 
  797                         em.getRootContext().setDisplayName(newCaseName);
 
  827                     SwingUtilities.invokeLater(() -> {
 
  838             else if (changed.equals(ExplorerManager.PROP_SELECTED_NODES)) {
 
  839                 respondSelection((Node[]) event.getOldValue(), (Node[]) event.getNewValue());
 
  852     @NbBundle.Messages(
"DirectoryTreeTopComponent.emptyMimeNode.text=Data not available. Run file type identification module.")
 
  853     void respondSelection(
final Node[] oldNodes, 
final Node[] newNodes) {
 
  863         EventQueue.invokeLater(() -> {
 
  865             DirectoryTreeTopComponent.this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
 
  867                 Node treeNode = DirectoryTreeTopComponent.this.getSelectedNode();
 
  868                 if (treeNode != null) {
 
  869                     Node originNode = ((DirectoryTreeFilterNode) treeNode).getOriginal();
 
  871                     Node drfn = 
new DataResultFilterNode(originNode, DirectoryTreeTopComponent.this.em);
 
  873                     if (FileTypesByMimeType.isEmptyMimeTypeNode(originNode)) {
 
  876                         EmptyNode emptyNode = 
new EmptyNode(Bundle.DirectoryTreeTopComponent_emptyMimeNode_text());
 
  877                         dataResult.
setNode(
new TableFilterNode(emptyNode, 
true, 
"This Node Is Empty")); 
 
  878                     } 
else if (originNode instanceof DisplayableItemNode) {
 
  879                         dataResult.
setNode(
new TableFilterNode(drfn, 
true, ((DisplayableItemNode) originNode).getItemType()));
 
  881                         dataResult.
setNode(
new TableFilterNode(drfn, 
true));
 
  883                     String displayName = 
"";
 
  884                     Content content = originNode.getLookup().lookup(Content.class);
 
  885                     if (content != null) {
 
  887                             displayName = content.getUniquePath();
 
  888                         } 
catch (TskCoreException ex) {
 
  889                             LOGGER.log(Level.SEVERE, 
"Exception while calling Content.getUniquePath() for node: {0}", originNode); 
 
  891                     } 
else if (originNode.getLookup().lookup(String.class) != null) {
 
  892                         displayName = originNode.getLookup().lookup(String.class);
 
  894                     dataResult.
setPath(displayName);
 
  897                 if (oldNodes != null && newNodes != null
 
  898                         && (oldNodes.length == newNodes.length)) {
 
  899                     boolean sameNodes = 
true;
 
  900                     for (
int i = 0; i < oldNodes.length; i++) {
 
  901                         sameNodes = sameNodes && oldNodes[i].getName().equals(newNodes[i].getName());
 
  904                         dataResult.requestActive();
 
  913         updateHistory(em.getSelectedNodes());
 
  917         if (selectedNodes.length == 0) {
 
  921         Node selectedNode = selectedNodes[0];
 
  922         String selectedNodeName = selectedNode.getName();
 
  930         String[] currentLast = backList.peekLast();
 
  931         String lastNodeName = null;
 
  932         if (currentLast != null && currentLast.length > 0) {
 
  933             lastNodeName = currentLast[currentLast.length - 1];
 
  936         if (currentLast == null || !selectedNodeName.equals(lastNodeName)) {
 
  938             final String[] selectedPath = NodeOp.createPath(selectedNode, em.getRootContext());
 
  939             backList.addLast(selectedPath); 
 
  940             if (backList.size() > 1) {
 
  941                 backButton.setEnabled(
true);
 
  943                 backButton.setEnabled(
false);
 
  947             forwardButton.setEnabled(
false); 
 
  959         backButton.setEnabled(
false);
 
  960         forwardButton.setEnabled(
false);
 
  968     BeanTreeView getTree() {
 
  969         return (BeanTreeView) this.treeView;
 
  976         SwingUtilities.invokeLater(this::rebuildTree);
 
  983         SwingUtilities.invokeLater(() -> {
 
  985             if (autopsyTreeChildren == null) {
 
  990                 for (Node dataSource : autopsyTreeChildren.getNodes()) {
 
  992                     if (tagsNode != null) {
 
  999                 if (tagsNode != null) {
 
 1012         Case currentCase = null;
 
 1019         if (!caseHasData(currentCase)) {
 
 1029         new SwingWorker<Void, Void>() {
 
 1032             protected Void doInBackground() 
throws Exception {
 
 1037             protected void done() {
 
 1042                     preExpandNodes(em.getRootContext().getChildren());
 
 1043                 } 
catch (InterruptedException | ExecutionException ex) {
 
 1044                     LOGGER.log(Level.SEVERE, 
"Error selecting tree node.", ex); 
 
 1060         if (null == currentCase) {
 
 1063             hasData = currentCase.
hasData();
 
 1075     private void setSelectedNode(
final String[] previouslySelectedNodePath, 
final String rootNodeName) {
 
 1076         if (previouslySelectedNodePath == null) {
 
 1079         SwingUtilities.invokeLater(
new Runnable() {
 
 1082                 if (previouslySelectedNodePath.length > 0 && (rootNodeName == null || previouslySelectedNodePath[0].equals(rootNodeName))) {
 
 1083                     Node selectedNode = null;
 
 1084                     ArrayList<String> selectedNodePath = 
new ArrayList<>(Arrays.asList(previouslySelectedNodePath));
 
 1085                     while (null == selectedNode && !selectedNodePath.isEmpty()) {
 
 1087                             selectedNode = NodeOp.findPath(em.getRootContext(), selectedNodePath.toArray(
new String[selectedNodePath.size()]));
 
 1088                         } 
catch (NodeNotFoundException ex) {
 
 1090                             if (selectedNodePath.size() > 1) {
 
 1091                                 selectedNodePath.remove(selectedNodePath.size() - 1);
 
 1093                                 StringBuilder nodePath = 
new StringBuilder();
 
 1094                                 for (
int i = 0; i < previouslySelectedNodePath.length; ++i) {
 
 1095                                     nodePath.append(previouslySelectedNodePath[i]).append(
"/");
 
 1097                                 LOGGER.log(Level.WARNING, 
"Failed to find any nodes to select on path " + nodePath.toString(), ex); 
 
 1103                     if (null != selectedNode) {
 
 1104                         if (rootNodeName != null) {
 
 1107                             backList.pollLast();
 
 1110                             em.setExploredContextAndSelection(selectedNode, 
new Node[]{selectedNode});
 
 1111                         } 
catch (PropertyVetoException ex) {
 
 1112                             LOGGER.log(Level.WARNING, 
"Property veto from ExplorerManager setting selection to " + selectedNode.getName(), ex); 
 
 1144             case ANALYSIS_RESULT:
 
 1147                 LOGGER.log(Level.WARNING, 
"Unbale to find category of type: " + category.name());
 
 1148                 return Optional.empty();
 
 1166             return Optional.empty();
 
 1167         } 
else if (node.getLookup().lookup(
Host.class) != null
 
 1168                 || node.getLookup().lookup(
Person.class) != null
 
 1171             Children children = node.getChildren();
 
 1173             Stream<Node> childNodeStream = children == null ? Stream.empty() : Stream.of(children.getNodes());
 
 1174             return childNodeStream
 
 1175                     .map(childNode -> searchForCategoryNode(childNode, dataSourceId, category))
 
 1176                     .filter(Optional::isPresent)
 
 1182             if (dataSource != null && dataSource.
getId() == dataSourceId) {
 
 1184                 if (dsChildren != null) {
 
 1185                     return getCategoryNodeChild(dsChildren, category);
 
 1189             return Optional.empty();
 
 1203         Children rootChildren = em.getRootContext().getChildren();
 
 1204         Optional<Node> categoryNode = getCategoryNodeChild(rootChildren, category);
 
 1205         if (categoryNode.isPresent()) {
 
 1206             return categoryNode;
 
 1213             LOGGER.log(Level.WARNING, 
"There was an error fetching the data source id for artifact.", ex);
 
 1217         Node[] rootNodes = rootChildren.getNodes();
 
 1218         Stream<Node> rootNodesStream = rootNodes == null ? Stream.empty() : Stream.of(rootNodes);
 
 1219         return rootNodesStream
 
 1220                 .map((rootNode) -> searchForCategoryNode(rootNode, dataSourceId, category))
 
 1221                 .filter(Optional::isPresent)
 
 1238             return Optional.empty();
 
 1241         Host nodeHost = node.getLookup().lookup(
Host.class);
 
 1242         if ((nodeHost != null && hosts != null && hosts.contains(nodeHost))
 
 1243                 || node.getLookup().lookup(
DataSource.class) != null
 
 1244                 || node.getLookup().lookup(
Person.class) != null
 
 1247             return Stream.of(node.getChildren().getNodes(
true))
 
 1248                     .map(childNode -> getOsAccountListNode(childNode, osAccount, hosts))
 
 1249                     .filter(Optional::isPresent)
 
 1256             return Optional.of(node);
 
 1259         return Optional.empty();
 
 1268         Set<Host> hosts = null;
 
 1274                 LOGGER.log(Level.WARNING, 
"Unable to get valid hosts for osAccount: " + osAccount, ex);
 
 1279         final Set<Host> finalHosts = hosts;
 
 1281         Optional<Node> osAccountListNodeOpt = Stream.of(em.getRootContext().getChildren().getNodes(
true))
 
 1282                 .map(nd -> getOsAccountListNode(nd, osAccount, finalHosts))
 
 1283                 .filter(Optional::isPresent)
 
 1287         if (!osAccountListNodeOpt.isPresent()) {
 
 1291         Node osAccountListNode = osAccountListNodeOpt.get();
 
 1293         DisplayableItemNode undecoratedParentNode = (DisplayableItemNode) ((DirectoryTreeFilterNode) osAccountListNode).getOriginal();
 
 1296             return osAcctOfNd != null && osAcctOfNd.
getId() == osAccount.
getId();
 
 1298         getTree().expandNode(osAccountListNode);
 
 1300             em.setExploredContextAndSelection(osAccountListNode, 
new Node[]{osAccountListNode});
 
 1301         } 
catch (PropertyVetoException ex) {
 
 1302             LOGGER.log(Level.WARNING, 
"Property Veto: ", ex); 
 
 1316                     .filter(type -> type.getTypeID() == artifactTypeId)
 
 1319             LOGGER.log(Level.WARNING, 
"Error occurred while looking up blackboard artifact type for: " + artifactTypeId, ex);
 
 1320             return Optional.empty();
 
 1338     @SuppressWarnings(
"deprecation")
 
 1340         int typeID = art.getArtifactTypeID();
 
 1341         String typeName = art.getArtifactTypeName();
 
 1344         Optional<Children> categoryChildrenOpt = typeOpt
 
 1345                 .flatMap(type -> getCategoryNode(type.getCategory(), art))
 
 1346                 .flatMap(categoryNode -> Optional.ofNullable(categoryNode.getChildren()));
 
 1348         if (!categoryChildrenOpt.isPresent()) {
 
 1349             LOGGER.log(Level.WARNING, String.format(
"Category node children for artifact of typeID: %d and artifactID: %d not found.",
 
 1350                     typeID, art.getArtifactID()));
 
 1354         Children typesChildren = categoryChildrenOpt.get();
 
 1356         Node treeNode = null;
 
 1358             treeNode = getHashsetNode(typesChildren, art);
 
 1360             treeNode = getKeywordHitNode(typesChildren, art);
 
 1368             treeNode = getEmailNode(typesChildren, art);
 
 1370             treeNode = getAccountNode(typesChildren, art);
 
 1372             treeNode = typesChildren.findChild(typeName);
 
 1375         if (treeNode == null) {
 
 1379         DisplayableItemNode undecoratedParentNode = (DisplayableItemNode) ((DirectoryTreeFilterNode) treeNode).getOriginal();
 
 1381         getTree().expandNode(treeNode);
 
 1382         if (this.getSelectedNode().equals(treeNode)) {
 
 1383             this.setDirectoryListingActive();
 
 1384             this.respondSelection(em.getSelectedNodes(), 
new Node[]{treeNode});
 
 1387                 em.setExploredContextAndSelection(treeNode, 
new Node[]{treeNode});
 
 1388             } 
catch (PropertyVetoException ex) {
 
 1389                 LOGGER.log(Level.WARNING, 
"Property Veto: ", ex); 
 
 1408         Children hashsetRootChilds = hashsetRootNode.getChildren();
 
 1410             String setName = null;
 
 1413                 int typeId = att.getAttributeType().getTypeID();
 
 1415                     setName = att.getValueString();
 
 1418             return hashsetRootChilds.findChild(setName);
 
 1420             LOGGER.log(Level.WARNING, 
"Error retrieving attributes", ex); 
 
 1438         Children keywordRootChilds = keywordRootNode.getChildren();
 
 1440             String listName = null;
 
 1441             String keywordName = null;
 
 1442             String regex = null;
 
 1445                 int typeId = att.getAttributeType().getTypeID();
 
 1447                     listName = att.getValueString();
 
 1449                     keywordName = att.getValueString();
 
 1451                     regex = att.getValueString();
 
 1454             if (listName == null) {
 
 1455                 if (regex == null) {  
 
 1456                     listName = NbBundle.getMessage(
KeywordHits.class, 
"KeywordHits.simpleLiteralSearch.text");
 
 1458                     listName = NbBundle.getMessage(
KeywordHits.class, 
"KeywordHits.singleRegexSearch.text");
 
 1461             Node listNode = keywordRootChilds.findChild(listName);
 
 1462             if (listNode == null) {
 
 1465             Children listChildren = listNode.getChildren();
 
 1466             if (listChildren == null) {
 
 1469             if (regex != null) {  
 
 1470                 Node regexNode = listChildren.findChild(listName);
 
 1471                 regexNode = (regexNode == null) ? listChildren.findChild(listName + 
"_" + regex) : regexNode;
 
 1472                 if (regexNode == null) {
 
 1475                 listChildren = regexNode.getChildren();
 
 1476                 if (listChildren == null) {
 
 1481             return listChildren.findChild(keywordName);
 
 1483             LOGGER.log(Level.WARNING, 
"Error retrieving attributes", ex); 
 
 1502         Node interestingItemsRootNode = typesChildren.findChild(artifactType.getDisplayName());
 
 1503         Children setNodeChildren = (interestingItemsRootNode == null) ? null : interestingItemsRootNode.getChildren();
 
 1506         if (setNodeChildren == null) {
 
 1510         String setName = null;
 
 1514                     .map(attr -> attr.getValueString())
 
 1519             LOGGER.log(Level.WARNING, 
"Error retrieving attributes", ex); 
 
 1524         if (setName == null) {
 
 1529         final String finalSetName = setName;
 
 1530         return Stream.of(setNodeChildren.getNodes(
true))
 
 1531                 .filter(setNode -> finalSetName.equals(setNode.getLookup().lookup(String.class)))
 
 1546         Children emailMsgRootChilds = emailMsgRootNode.getChildren();
 
 1547         Map<String, String> parsedPath = null;
 
 1551                 int typeId = att.getAttributeType().getTypeID();
 
 1557             if (parsedPath == null) {
 
 1560             Node defaultNode = emailMsgRootChilds.findChild(parsedPath.get(NbBundle.getMessage(
EmailExtracted.class, 
"EmailExtracted.defaultAcct.text")));
 
 1561             Children defaultChildren = defaultNode.getChildren();
 
 1562             return defaultChildren.findChild(parsedPath.get(NbBundle.getMessage(
EmailExtracted.class, 
"EmailExtracted.defaultFolder.text")));
 
 1564             LOGGER.log(Level.WARNING, 
"Error retrieving attributes", ex); 
 
 1579         Node accountRootNode = typesChildren.findChild(art.
getDisplayName());
 
 1580         Children accountRootChilds = accountRootNode.getChildren();
 
 1581         List<BlackboardAttribute> attributes;
 
 1582         String accountType = null;
 
 1583         String ccNumberName = null;
 
 1587                 int typeId = att.getAttributeType().getTypeID();
 
 1589                     accountType = att.getValueString();
 
 1592                     ccNumberName = att.getValueString();
 
 1595             if (accountType == null) {
 
 1600                 return getCreditCardAccountNode(accountRootChilds, ccNumberName);
 
 1602                 return accountRootChilds.findChild(accountType);
 
 1605             LOGGER.log(Level.WARNING, 
"Error retrieving attributes", ex); 
 
 1622         if (accountNode == null) {
 
 1625         Children accountChildren = accountNode.getChildren();
 
 1626         if (accountChildren == null) {
 
 1629         Node binNode = accountChildren.findChild(NbBundle.getMessage(
Accounts.class, 
"Accounts.ByBINNode.name"));
 
 1630         if (binNode == null) {
 
 1633         Children binChildren = binNode.getChildren();
 
 1634         if (ccNumberName == null) {
 
 1639         String binName = StringUtils.rightPad(ccNumberName, 8, 
"0");
 
 1640         binName = binName.substring(0, 8);
 
 1643             bin = Integer.parseInt(binName);
 
 1644         } 
catch (NumberFormatException ex) {
 
 1645             LOGGER.log(Level.WARNING, 
"Unable to parseInt a BIN for node selection from string binName=" + binName, ex); 
 
 1649         if (binInfo != null) {
 
 1650             int startBin = ((
BINRange) binInfo).getBINstart();
 
 1651             int endBin = ((
BINRange) binInfo).getBINend();
 
 1652             if (startBin != endBin) {
 
 1653                 binName = Integer.toString(startBin) + 
"-" + Integer.toString(endBin).substring(5); 
 
 1656         if (binName == null) {
 
 1659         return binChildren.findChild(binName);
 
 1664                 NbBundle.getMessage(
this.getClass(), 
"DirectoryTreeTopComponent.action.viewArtContent.text"),
 
static synchronized String getConfigSetting(String moduleName, String settingName)
List< Content > getDataSources()
TopComponent getTopComponent()
Children autopsyTreeChildren
static final String HIDE_SLACK_FILES_IN_VIEWS_TREE
Node getAccountNode(Children typesChildren, BlackboardArtifact art)
javax.swing.JScrollPane treeView
Node getCreditCardAccountNode(Children accountRootChildren, String ccNumberName)
List< Host > getHosts(OsAccount account)
static boolean caseHasData(Case currentCase)
static final String HIDE_KNOWN_FILES_IN_VIEWS_TREE
DataResultTopComponent getDirectoryListing()
final LinkedList< String[]> forwardList
void setDirectoryListingActive()
static boolean runningWithGUI
void setShowRejected(boolean showRejected)
static final Type TSK_KEYWORD_HIT
static final String HIDE_SCO_COLUMNS
String getArtifactTypeName()
void setSelectedNode(final String[] previouslySelectedNodePath, final String rootNodeName)
Optional< Node > getCategoryNodeChild(Children children, Category category)
javax.swing.JButton openViewPreferencesButton
static final Type TSK_INTERESTING_ARTIFACT_HIT
boolean hasMenuOpenAction()
static void openCoreWindows()
static final String TEXT_TRANSLATOR_NAME
void updateHistory(Node[] selectedNodes)
final LinkedList< String[]> backList
static synchronized BankIdentificationNumber getBINInfo(int bin)
void openDirectoryListing()
Optional< BlackboardArtifact.Type > getType(long artifactTypeId)
void refreshContentTreeSafe()
void readPropertiesImpl(java.util.Properties p)
void backButtonActionPerformed(java.awt.event.ActionEvent evt)
void setShowRejectedResults(boolean showRejectedResults)
static final String SHOW_ONLY_CURRENT_USER_TAGS
void propertyChange(PropertyChangeEvent event)
List< BlackboardArtifact.Type > getArtifactTypesInUse()
static final String HIDE_KNOWN_FILES_IN_DATA_SRCS_TREE
AutopsyTreeChildFactory autopsyTreeChildFactory
static String getUnknownPersonId()
Optional< Node > searchForCategoryNode(Node node, long dataSourceId, Category category)
Node getEmailNode(Children typesChildren, BlackboardArtifact art)
static synchronized boolean settingExists(String moduleName, String settingName)
Optional< Node > getOsAccountListNode(Node node, OsAccount osAccount, Set< Host > hosts)
List< Content > getChildren()
DirectoryTreeTopComponent()
static synchronized DirectoryTreeTopComponent getDefault()
static final String DISPLAY_TIMES_IN_LOCAL_TIME
javax.swing.JButton forwardButton
static void setGroupItemsInTreeByDataSource(boolean value)
static final Type TSK_ACCOUNT
static final String KEEP_PREFERRED_VIEWER
static synchronized void setConfigSetting(String moduleName, String settingName, String settingVal)
Optional< Node > getCategoryNode(Category category, BlackboardArtifact art)
boolean showRejectedResults
static final Account.Type CREDIT_CARD
void viewArtifactContent(BlackboardArtifact art)
static final String DISPLAY_TRANSLATED_NAMES
Node getHashsetNode(Children typesChildren, final BlackboardArtifact art)
void promptForDataSourceGrouping(int dataSourceCount)
ExplorerManager getExplorerManager()
javax.swing.JButton backButton
static final String HIDE_SLACK_FILES_IN_DATA_SRCS_TREE
SleuthkitCase getSleuthkitCase()
void preExpandNodes(Children rootChildren)
static Boolean getGroupItemsInTreeByDataSource()
List< BlackboardAttribute > getAttributes()
static final Type TSK_HASHSET_HIT
static DirectoryTreeTopComponent instance
void addOnFinishedListener(PropertyChangeListener l)
Node getKeywordHitNode(Children typesChildren, BlackboardArtifact art)
static String getListName()
static final String MAIN_SETTINGS
static final Type TSK_SET_NAME
OsAccountManager getOsAccountManager()
static Case getCurrentCase()
synchronized static Logger getLogger(String name)
static final Type TSK_EMAIL_MSG
static Case getCurrentCaseThrows()
List< Node > getHostNodesAndParents(Node node)
boolean getShowRejectedResults()
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
static void addChangeListener(PreferenceChangeListener listener)
void viewOsAccount(OsAccount osAccount)
javax.swing.JPopupMenu viewPreferencesPopupMenu
void setChildNodeSelectionInfo(NodeSelectionInfo selectedChildNodeInfo)
void forwardButtonActionPerformed(java.awt.event.ActionEvent evt)
void subscribeToChangeEvents()
static synchronized DirectoryTreeTopComponent findInstance()
void setPath(String pathText)
static final Type TSK_INTERESTING_ITEM
static final String TIME_ZONE_FOR_DISPLAYS
static boolean isCaseOpen()
Node getInterestingItemNode(Children typesChildren, BlackboardArtifact.Type artifactType, BlackboardArtifact art)
static final Type TSK_INTERESTING_FILE_HIT
void openViewPreferencesButtonActionPerformed(java.awt.event.ActionEvent evt)
void setNode(Node selectedNode)