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.HashSet;
 
   30 import java.util.LinkedList;
 
   31 import java.util.List;
 
   32 import java.util.logging.Level;
 
   33 import java.util.prefs.PreferenceChangeEvent;
 
   34 import java.util.prefs.PreferenceChangeListener;
 
   35 import javax.swing.Action;
 
   36 import javax.swing.SwingUtilities;
 
   37 import javax.swing.tree.TreeSelectionModel;
 
   38 import org.openide.explorer.ExplorerManager;
 
   39 import org.openide.explorer.ExplorerUtils;
 
   40 import org.openide.explorer.view.BeanTreeView;
 
   41 import org.openide.explorer.view.TreeView;
 
   42 import org.openide.nodes.AbstractNode;
 
   43 import org.openide.nodes.Children;
 
   44 import org.openide.nodes.Node;
 
   45 import org.openide.nodes.NodeNotFoundException;
 
   46 import org.openide.nodes.NodeOp;
 
   47 import org.openide.util.NbBundle;
 
   48 import org.openide.windows.TopComponent;
 
   49 import org.openide.windows.WindowManager;
 
   88     private final transient ExplorerManager 
em = 
new ExplorerManager();
 
   91             "DirectoryTreeTopComponent.title.text"));
 
   94     private static final String 
PREFERRED_ID = 
"DirectoryTreeTopComponent"; 
 
  105         ((BeanTreeView) 
jScrollPane1).setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
 
  107         putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE);
 
  112         associateLookup(ExplorerUtils.createLookup(em, getActionMap()));
 
  115         this.backList = 
new LinkedList<>();
 
  116         this.forwardList = 
new LinkedList<>();
 
  127             public void preferenceChange(PreferenceChangeEvent evt) {
 
  128                 switch (evt.getKey()) {
 
  139         this.em.addPropertyChangeListener(
this);
 
  145         this.dataResult.requestActive();
 
  149         this.dataResult.
open();
 
  171         backButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_back.png"))); 
 
  175         backButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_back_disabled.png"))); 
 
  176         backButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
 
  177         backButton.setMaximumSize(
new java.awt.Dimension(55, 100));
 
  178         backButton.setMinimumSize(
new java.awt.Dimension(5, 5));
 
  179         backButton.setPreferredSize(
new java.awt.Dimension(23, 23));
 
  180         backButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_back_hover.png"))); 
 
  181         backButton.addActionListener(
new java.awt.event.ActionListener() {
 
  182             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  187         forwardButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_forward.png"))); 
 
  191         forwardButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_forward_disabled.png"))); 
 
  193         forwardButton.setMaximumSize(
new java.awt.Dimension(55, 100));
 
  195         forwardButton.setPreferredSize(
new java.awt.Dimension(23, 23));
 
  196         forwardButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_forward_hover.png"))); 
 
  197         forwardButton.addActionListener(
new java.awt.event.ActionListener() {
 
  198             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  205         javax.swing.GroupLayout layout = 
new javax.swing.GroupLayout(
this);
 
  206         this.setLayout(layout);
 
  207         layout.setHorizontalGroup(
 
  208             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  209             .addComponent(
jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 262, Short.MAX_VALUE)
 
  210             .addGroup(layout.createSequentialGroup()
 
  212                 .addComponent(
backButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  214                 .addComponent(
forwardButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  215                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 46, Short.MAX_VALUE)
 
  219         layout.setVerticalGroup(
 
  220             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  221             .addGroup(layout.createSequentialGroup()
 
  223                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
 
  224                     .addComponent(
forwardButton, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  225                     .addComponent(
backButton, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  227                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  228                 .addComponent(
jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 838, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  235         this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
 
  238         String[] currentNodePath = backList.pollLast();
 
  239         forwardList.addLast(currentNodePath);
 
  247         String[] newCurrentNodePath = backList.peekLast();
 
  250         if (backList.size() > 1) {
 
  259         this.setCursor(null);
 
  264         this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
 
  266         String[] newCurrentNodePath = forwardList.pollLast();
 
  267         if (!forwardList.isEmpty()) {
 
  273         backList.addLast(newCurrentNodePath);
 
  279         this.setCursor(null);
 
  296         if (instance == null) {
 
  307         WindowManager winManager = WindowManager.
getDefault();
 
  308         TopComponent win = winManager.findTopComponent(PREFERRED_ID);
 
  311                     "Cannot find " + PREFERRED_ID + 
" component. It will not be located properly in the window system."); 
 
  315             return (DirectoryTreeTopComponent) win;
 
  318                 "There seem to be multiple components with the '" + PREFERRED_ID 
 
  319                 + 
"' ID. That is a potential source of errors and unexpected behavior."); 
 
  331         return TopComponent.PERSISTENCE_NEVER;
 
  344         this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
 
  350                 if (currentCase.
hasData() == 
false) {
 
  352                     ((BeanTreeView) this.
jScrollPane1).setRootVisible(
false); 
 
  355                     List<Object> items = 
new ArrayList<>();
 
  358                     items.add(
new Views(tskCase));
 
  359                     items.add(
new Results(tskCase));
 
  360                     items.add(
new Tags());
 
  364                     Node root = 
new AbstractNode(contentChildren) {
 
  371                             return new Action[]{};
 
  377                         public Node.Handle getHandle() {
 
  378                             return new Node.Handle() {
 
  380                                 public Node getNode() 
throws IOException {
 
  381                                     return em.getRootContext();
 
  387                     root = 
new DirectoryTreeFilterNode(root, 
true);
 
  389                     em.setRootContext(root);
 
  390                     em.getRootContext().setName(currentCase.
getName());
 
  391                     em.getRootContext().setDisplayName(currentCase.
getName());
 
  392                     ((BeanTreeView) this.
jScrollPane1).setRootVisible(
false); 
 
  397                     Children childNodes = em.getRootContext().getChildren();
 
  401                     tree.expandNode(results);
 
  403                     Children resultsChilds = results.getChildren();
 
  412                     Children viewsChilds = views.getChildren();
 
  413                     for (Node n : viewsChilds.getNodes()) {
 
  417                     tree.collapseNode(views);
 
  420                     if (!dataResult.isOpened()) {
 
  428                     if (childNodes.getNodesCount() > 0) {
 
  430                             em.setSelectedNodes(
new Node[]{childNodes.getNodeAt(0)});
 
  431                         } 
catch (Exception ex) {
 
  432                             logger.log(Level.SEVERE, 
"Error setting default selected node.", ex); 
 
  439             this.setCursor(null);
 
  452         contentChildren = null;
 
  455     void writeProperties(java.util.Properties p) {
 
  458         p.setProperty(
"version", 
"1.0");
 
  462     Object readProperties(java.util.Properties p) {
 
  463         if (instance == null) {
 
  471         String version = p.getProperty(
"version");
 
  507         return new Action[]{};
 
  519         if (selectedNodes.length > 0) {
 
  520             result = selectedNodes[0];
 
  534             String changed = evt.getPropertyName();
 
  544                 if (evt.getOldValue() != null && evt.getNewValue() == null) {
 
  546                     SwingUtilities.invokeLater(() -> {
 
  547                         Node emptyNode = 
new AbstractNode(Children.LEAF);
 
  548                         em.setRootContext(emptyNode);
 
  550                 } 
else if (evt.getNewValue() != null) {
 
  552                     Case newCase = (
Case) evt.getNewValue();
 
  553                     final String newCaseName = newCase.
getName();
 
  554                     SwingUtilities.invokeLater(() -> {
 
  555                         em.getRootContext().setName(newCaseName);
 
  556                         em.getRootContext().setDisplayName(newCaseName);
 
  580                         SwingUtilities.invokeLater(() -> {
 
  584                 } 
catch (IllegalStateException | TskCoreException notUsed) {
 
  590             else if (changed.equals(ExplorerManager.PROP_SELECTED_NODES)) {
 
  591                 SwingUtilities.invokeLater(() -> {
 
  621         EventQueue.invokeLater(
new Runnable() {
 
  629                     if (treeNode != null) {
 
  630                         DirectoryTreeFilterNode.OriginalNode origin = treeNode.getLookup().lookup(DirectoryTreeFilterNode.OriginalNode.class);
 
  631                         if (origin == null) {
 
  634                         Node originNode = origin.getNode();
 
  652                         String displayName = 
"";
 
  653                         Content content = originNode.getLookup().lookup(Content.class);
 
  654                         if (content != null) {
 
  656                                 displayName = content.getUniquePath();
 
  657                             } 
catch (TskCoreException ex) {
 
  658                                 logger.log(Level.SEVERE, 
"Exception while calling Content.getUniquePath() for node: " + originNode); 
 
  660                         } 
else if (originNode.getLookup().lookup(String.class) != null) {
 
  661                             displayName = originNode.getLookup().lookup(String.class);
 
  663                         dataResult.
setPath(displayName);
 
  667                     if (oldNodes != null && newNodes != null
 
  668                             && (oldNodes.length == newNodes.length)) {
 
  669                         boolean sameNodes = 
true;
 
  670                         for (
int i = 0; i < oldNodes.length; i++) {
 
  671                             sameNodes = sameNodes && oldNodes[i].getName().equals(newNodes[i].getName());
 
  674                             dataResult.requestActive();
 
  688         if (selectedNodes.length == 0) {
 
  692         Node selectedNode = selectedNodes[0];
 
  693         String selectedNodeName = selectedNode.getName();
 
  701         String[] currentLast = backList.peekLast();
 
  702         String lastNodeName = null;
 
  703         if (currentLast != null) {
 
  704             lastNodeName = currentLast[currentLast.length - 1];
 
  707         if (currentLast == null || !selectedNodeName.equals(lastNodeName)) {
 
  709             final String[] selectedPath = NodeOp.createPath(selectedNode, em.getRootContext());
 
  710             backList.addLast(selectedPath); 
 
  711             if (backList.size() > 1) {
 
  747         SwingUtilities.invokeLater(
new Runnable() {
 
  760         final String[] selectedPath = NodeOp.createPath(selectedNode, em.getRootContext());
 
  762         Children rootChildren = em.getRootContext().getChildren();
 
  764         if (dataSourcesFilterNode == null) {
 
  765             logger.log(Level.SEVERE, 
"Cannot find data sources filter node, won't refresh the content tree"); 
 
  768         DirectoryTreeFilterNode.OriginalNode imagesNodeOrig = dataSourcesFilterNode.getLookup().lookup(DirectoryTreeFilterNode.OriginalNode.class);
 
  770         if (imagesNodeOrig == null) {
 
  771             logger.log(Level.SEVERE, 
"Cannot find data sources node, won't refresh the content tree"); 
 
  775         Node imagesNode = imagesNodeOrig.getNode();
 
  793     private void setSelectedNode(
final String[] previouslySelectedNodePath, 
final String rootNodeName) {
 
  794         if (previouslySelectedNodePath == null) {
 
  797         SwingUtilities.invokeLater(
new Runnable() {
 
  800                 if (previouslySelectedNodePath.length > 0 && (rootNodeName == null || previouslySelectedNodePath[0].equals(rootNodeName))) {
 
  801                     Node selectedNode = null;
 
  802                     ArrayList<String> selectedNodePath = 
new ArrayList<>(Arrays.asList(previouslySelectedNodePath));
 
  803                     while (null == selectedNode && !selectedNodePath.isEmpty()) {
 
  805                             selectedNode = NodeOp.findPath(em.getRootContext(), selectedNodePath.toArray(
new String[0]));
 
  806                         } 
catch (NodeNotFoundException ex) {
 
  808                             if (selectedNodePath.size() > 1) {
 
  809                                 selectedNodePath.remove(selectedNodePath.size() - 1);
 
  811                                 StringBuilder nodePath = 
new StringBuilder();
 
  812                                 for (
int i = 0; i < previouslySelectedNodePath.length; ++i) {
 
  813                                     nodePath.append(previouslySelectedNodePath[i]).append(
"/");
 
  815                                 logger.log(Level.WARNING, 
"Failed to find any nodes to select on path " + nodePath.toString(), ex); 
 
  821                     if (null != selectedNode) {
 
  822                         if (rootNodeName != null) {
 
  828                             em.setExploredContextAndSelection(selectedNode, 
new Node[]{selectedNode});
 
  829                         } 
catch (PropertyVetoException ex) {
 
  830                             logger.log(Level.WARNING, 
"Property veto from ExplorerManager setting selection to " + selectedNode.getName(), ex); 
 
  850         int typeID = art.getArtifactTypeID();
 
  851         String typeName = art.getArtifactTypeName();
 
  852         Children rootChilds = em.getRootContext().getChildren();
 
  853         Node treeNode = null;
 
  855         Children resultsChilds = resultsNode.getChildren();
 
  856         if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) {
 
  857             Node hashsetRootNode = resultsChilds.findChild(typeName);
 
  858             Children hashsetRootChilds = hashsetRootNode.getChildren();
 
  860                 String setName = null;
 
  861                 List<BlackboardAttribute> attributes = art.getAttributes();
 
  862                 for (BlackboardAttribute att : attributes) {
 
  863                     int typeId = att.getAttributeType().getTypeID();
 
  864                     if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
 
  865                         setName = att.getValueString();
 
  868                 treeNode = hashsetRootChilds.findChild(setName);
 
  869             } 
catch (TskException ex) {
 
  870                 logger.log(Level.WARNING, 
"Error retrieving attributes", ex); 
 
  872         } 
else if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
 
  873             Node keywordRootNode = resultsChilds.findChild(typeName);
 
  874             Children keywordRootChilds = keywordRootNode.getChildren();
 
  876                 String listName = null;
 
  877                 String keywordName = null;
 
  878                 List<BlackboardAttribute> attributes = art.getAttributes();
 
  879                 for (BlackboardAttribute att : attributes) {
 
  880                     int typeId = att.getAttributeType().getTypeID();
 
  881                     if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
 
  882                         listName = att.getValueString();
 
  883                     } 
else if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) {
 
  884                         keywordName = att.getValueString();
 
  887                 Node listNode = keywordRootChilds.findChild(listName);
 
  888                 if (listNode == null) {
 
  891                 Children listChildren = listNode.getChildren();
 
  892                 if (listChildren == null) {
 
  895                 treeNode = listChildren.findChild(keywordName);
 
  896             } 
catch (TskException ex) {
 
  897                 logger.log(Level.WARNING, 
"Error retrieving attributes", ex); 
 
  899         } 
else if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID()
 
  900                 || typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
 
  901             Node interestingItemsRootNode = resultsChilds.findChild(typeName);
 
  902             Children interestingItemsRootChildren = interestingItemsRootNode.getChildren();
 
  904                 String setName = null;
 
  905                 List<BlackboardAttribute> attributes = art.getAttributes();
 
  906                 for (BlackboardAttribute att : attributes) {
 
  907                     int typeId = att.getAttributeType().getTypeID();
 
  908                     if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
 
  909                         setName = att.getValueString();
 
  912                 treeNode = interestingItemsRootChildren.findChild(setName);
 
  913             } 
catch (TskException ex) {
 
  914                 logger.log(Level.WARNING, 
"Error retrieving attributes", ex); 
 
  918             Children extractedChilds = extractedContent.getChildren();
 
  919             if (extractedChilds == null) {
 
  922             treeNode = extractedChilds.findChild(typeName);
 
  925         if (treeNode == null) {
 
  930             em.setExploredContextAndSelection(treeNode, 
new Node[]{treeNode});
 
  931         } 
catch (PropertyVetoException ex) {
 
  932             logger.log(Level.WARNING, 
"Property Veto: ", ex); 
 
  936         EventQueue.invokeLater(
new Runnable() {
 
  939                 Children resultChilds = dataResult.
getRootNode().getChildren();
 
  940                 Node select = resultChilds.findChild(Long.toString(art.getArtifactID()));
 
  941                 if (select != null) {
 
  942                     dataResult.requestActive();
 
  944                     fireViewerComplete();
 
  953                 NbBundle.getMessage(
this.getClass(), 
"DirectoryTreeTopComponent.action.viewArtContent.text"),
 
  962     void fireViewerComplete() {
 
  966         } 
catch (Exception e) {
 
  967             logger.log(Level.SEVERE, 
"DirectoryTreeTopComponent listener threw exception", e); 
 
  968             MessageNotifyUtil.Notify.show(NbBundle.getMessage(
this.getClass(), 
"DirectoryTreeTopComponent.moduleErr"),
 
  969                     NbBundle.getMessage(
this.getClass(),
 
  970                             "DirectoryTreeTopComponent.moduleErr.msg"),
 
  971                     MessageNotifyUtil.MessageType.ERROR);
 
List< Content > getDataSources()
TopComponent getTopComponent()
void viewArtifact(final BlackboardArtifact art)
static final Logger logger
final DataResultTopComponent dataResult
static final String HIDE_KNOWN_FILES_IN_DATA_SOURCES_TREE
static final String HIDE_KNOWN_FILES_IN_VIEWS_TREE
javax.swing.JCheckBox showRejectedCheckBox
static synchronized IngestManager getInstance()
DataResultTopComponent getDirectoryListing()
final LinkedList< String[]> forwardList
void setDirectoryListingActive()
final transient ExplorerManager em
RootContentChildren contentChildren
void respondSelection(final Node[] oldNodes, final Node[] newNodes)
void setSelectedNode(final String[] previouslySelectedNodePath, final String rootNodeName)
boolean hasMenuOpenAction()
void propertyChange(PropertyChangeEvent evt)
static void openCoreWindows()
javax.swing.JScrollPane jScrollPane1
void updateHistory(Node[] selectedNodes)
final LinkedList< String[]> backList
void openDirectoryListing()
void refreshContentTreeSafe()
void readPropertiesImpl(java.util.Properties p)
void backButtonActionPerformed(java.awt.event.ActionEvent evt)
static final String FINISHED_DISPLAY_EVT
DirectoryTreeTopComponent()
static synchronized DirectoryTreeTopComponent getDefault()
static final String PREFERRED_ID
javax.swing.JButton forwardButton
void addIngestJobEventListener(final PropertyChangeListener listener)
void refreshContentKeys()
void viewArtifactContent(BlackboardArtifact art)
static boolean coreComponentsAreActive()
void refreshDataSourceTree()
Action newToggleShowRejectedAction()
ExplorerManager getExplorerManager()
javax.swing.JButton backButton
SleuthkitCase getSleuthkitCase()
static SelectionContext getSelectionContext(Node n)
static DirectoryTreeTopComponent instance
void addOnFinishedListener(PropertyChangeListener l)
void addIngestModuleEventListener(final PropertyChangeListener listener)
static Case getCurrentCase()
synchronized static Logger getLogger(String name)
static void addChangeListener(PreferenceChangeListener listener)
void forwardButtonActionPerformed(java.awt.event.ActionEvent evt)
void setSelectedNodes(Node[] selected)
void subscribeToChangeEvents()
static synchronized DirectoryTreeTopComponent findInstance()
void setPath(String pathText)
static boolean isCaseOpen()
static void addEventSubscriber(Set< String > eventNames, PropertyChangeListener subscriber)
void setNode(Node selectedNode)