19 package org.sleuthkit.autopsy.directorytree;
22 import java.awt.Cursor;
23 import java.awt.EventQueue;
24 import java.beans.PropertyChangeEvent;
25 import java.beans.PropertyChangeListener;
26 import java.beans.PropertyVetoException;
27 import java.io.IOException;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.HashSet;
31 import java.util.LinkedList;
32 import java.util.List;
33 import java.util.logging.Level;
34 import java.util.prefs.PreferenceChangeEvent;
35 import java.util.prefs.PreferenceChangeListener;
36 import javax.swing.Action;
37 import javax.swing.SwingUtilities;
38 import javax.swing.tree.TreeSelectionModel;
39 import org.openide.explorer.ExplorerManager;
40 import org.openide.explorer.ExplorerUtils;
41 import org.openide.explorer.view.BeanTreeView;
42 import org.openide.explorer.view.TreeView;
43 import org.openide.nodes.AbstractNode;
44 import org.openide.nodes.Children;
45 import org.openide.nodes.Node;
46 import org.openide.nodes.NodeNotFoundException;
47 import org.openide.nodes.NodeOp;
48 import org.openide.util.NbBundle;
49 import org.openide.windows.TopComponent;
50 import org.openide.windows.WindowManager;
92 private final transient ExplorerManager
em =
new ExplorerManager();
95 "DirectoryTreeTopComponent.title.text"));
98 private static final String
PREFERRED_ID =
"DirectoryTreeTopComponent";
109 ((BeanTreeView)
jScrollPane1).setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
111 putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE);
116 associateLookup(ExplorerUtils.createLookup(em, getActionMap()));
119 this.backList =
new LinkedList<>();
120 this.forwardList =
new LinkedList<>();
131 public void preferenceChange(PreferenceChangeEvent evt) {
132 switch (evt.getKey()) {
145 this.em.addPropertyChangeListener(
this);
151 this.dataResult.requestActive();
155 this.dataResult.
open();
177 backButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_back.png")));
181 backButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_back_disabled.png")));
182 backButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
183 backButton.setMaximumSize(
new java.awt.Dimension(55, 100));
184 backButton.setMinimumSize(
new java.awt.Dimension(5, 5));
185 backButton.setPreferredSize(
new java.awt.Dimension(23, 23));
186 backButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_back_hover.png")));
187 backButton.addActionListener(
new java.awt.event.ActionListener() {
188 public void actionPerformed(java.awt.event.ActionEvent evt) {
193 forwardButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_forward.png")));
197 forwardButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_forward_disabled.png")));
199 forwardButton.setMaximumSize(
new java.awt.Dimension(55, 100));
201 forwardButton.setPreferredSize(
new java.awt.Dimension(23, 23));
202 forwardButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_forward_hover.png")));
203 forwardButton.addActionListener(
new java.awt.event.ActionListener() {
204 public void actionPerformed(java.awt.event.ActionEvent evt) {
211 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
212 this.setLayout(layout);
213 layout.setHorizontalGroup(
214 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
215 .addComponent(
jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 262, Short.MAX_VALUE)
216 .addGroup(layout.createSequentialGroup()
218 .addComponent(
backButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
220 .addComponent(
forwardButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
221 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 46, Short.MAX_VALUE)
225 layout.setVerticalGroup(
226 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
227 .addGroup(layout.createSequentialGroup()
229 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
230 .addComponent(
forwardButton, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
231 .addComponent(
backButton, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
233 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
234 .addComponent(
jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 838, javax.swing.GroupLayout.PREFERRED_SIZE)
241 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
244 String[] currentNodePath = backList.pollLast();
245 forwardList.addLast(currentNodePath);
253 String[] newCurrentNodePath = backList.peekLast();
256 if (backList.size() > 1) {
265 this.setCursor(null);
270 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
272 String[] newCurrentNodePath = forwardList.pollLast();
273 if (!forwardList.isEmpty()) {
279 backList.addLast(newCurrentNodePath);
285 this.setCursor(null);
302 if (instance == null) {
313 WindowManager winManager = WindowManager.
getDefault();
314 TopComponent win = winManager.findTopComponent(PREFERRED_ID);
317 "Cannot find " + PREFERRED_ID +
" component. It will not be located properly in the window system.");
321 return (DirectoryTreeTopComponent) win;
324 "There seem to be multiple components with the '" + PREFERRED_ID
325 +
"' ID. That is a potential source of errors and unexpected behavior.");
337 return TopComponent.PERSISTENCE_NEVER;
350 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
356 if (currentCase.
hasData() ==
false) {
358 ((BeanTreeView) this.
jScrollPane1).setRootVisible(
false);
361 List<Object> items =
new ArrayList<>();
364 items.add(
new Views(tskCase));
365 items.add(
new Results(tskCase));
366 items.add(
new Tags());
370 Node root =
new AbstractNode(contentChildren) {
377 return new Action[]{};
383 public Node.Handle getHandle() {
384 return new Node.Handle() {
386 public Node getNode()
throws IOException {
387 return em.getRootContext();
393 root =
new DirectoryTreeFilterNode(root,
true);
395 em.setRootContext(root);
396 em.getRootContext().setName(currentCase.
getName());
397 em.getRootContext().setDisplayName(currentCase.
getName());
398 ((BeanTreeView) this.
jScrollPane1).setRootVisible(
false);
403 Children childNodes = em.getRootContext().getChildren();
407 tree.expandNode(results);
409 Children resultsChilds = results.getChildren();
418 Children viewsChilds = views.getChildren();
419 for (Node n : viewsChilds.getNodes()) {
423 tree.collapseNode(views);
426 if (!dataResult.isOpened()) {
434 if (childNodes.getNodesCount() > 0) {
436 em.setSelectedNodes(
new Node[]{childNodes.getNodeAt(0)});
437 }
catch (Exception ex) {
438 LOGGER.log(Level.SEVERE,
"Error setting default selected node.", ex);
445 this.setCursor(null);
458 contentChildren = null;
461 void writeProperties(java.util.Properties p) {
464 p.setProperty(
"version",
"1.0");
468 Object readProperties(java.util.Properties p) {
469 if (instance == null) {
477 String version = p.getProperty(
"version");
513 return new Action[]{};
525 if (selectedNodes.length > 0) {
526 result = selectedNodes[0];
540 String changed = evt.getPropertyName();
550 if (evt.getOldValue() != null && evt.getNewValue() == null) {
552 SwingUtilities.invokeLater(() -> {
553 Node emptyNode =
new AbstractNode(Children.LEAF);
554 em.setRootContext(emptyNode);
556 }
else if (evt.getNewValue() != null) {
558 Case newCase = (
Case) evt.getNewValue();
559 final String newCaseName = newCase.
getName();
560 SwingUtilities.invokeLater(() -> {
561 em.getRootContext().setName(newCaseName);
562 em.getRootContext().setDisplayName(newCaseName);
586 SwingUtilities.invokeLater(() -> {
590 }
catch (IllegalStateException | TskCoreException notUsed) {
596 else if (changed.equals(ExplorerManager.PROP_SELECTED_NODES)) {
597 SwingUtilities.invokeLater(() -> {
607 @NbBundle.Messages(
"DirectoryTreeTopComponent.emptyMimeNode.text=Data not available. Run file type identification module.")
628 EventQueue.invokeLater(
new Runnable() {
636 if (treeNode != null) {
637 DirectoryTreeFilterNode.OriginalNode origin = treeNode.getLookup().lookup(DirectoryTreeFilterNode.OriginalNode.class);
638 if (origin == null) {
642 Node originNode = origin.getNode();
653 EmptyNode emptyNode =
new EmptyNode(Bundle.DirectoryTreeTopComponent_emptyMimeNode_text());
664 String displayName =
"";
665 Content content = originNode.getLookup().lookup(Content.class);
666 if (content != null) {
668 displayName = content.getUniquePath();
669 }
catch (TskCoreException ex) {
670 LOGGER.log(Level.SEVERE,
"Exception while calling Content.getUniquePath() for node: " + originNode);
672 }
else if (originNode.getLookup().lookup(String.class) != null) {
673 displayName = originNode.getLookup().lookup(String.class);
675 dataResult.
setPath(displayName);
679 if (oldNodes != null && newNodes != null
680 && (oldNodes.length == newNodes.length)) {
681 boolean sameNodes =
true;
682 for (
int i = 0; i < oldNodes.length; i++) {
683 sameNodes = sameNodes && oldNodes[i].getName().equals(newNodes[i].getName());
686 dataResult.requestActive();
700 if (selectedNodes.length == 0) {
704 Node selectedNode = selectedNodes[0];
705 String selectedNodeName = selectedNode.getName();
713 String[] currentLast = backList.peekLast();
714 String lastNodeName = null;
715 if (currentLast != null) {
716 lastNodeName = currentLast[currentLast.length - 1];
719 if (currentLast == null || !selectedNodeName.equals(lastNodeName)) {
721 final String[] selectedPath = NodeOp.createPath(selectedNode, em.getRootContext());
722 backList.addLast(selectedPath);
723 if (backList.size() > 1) {
759 SwingUtilities.invokeLater(
new Runnable() {
772 final String[] selectedPath = NodeOp.createPath(selectedNode, em.getRootContext());
774 Children rootChildren = em.getRootContext().getChildren();
776 if (dataSourcesFilterNode == null) {
777 LOGGER.log(Level.SEVERE,
"Cannot find data sources filter node, won't refresh the content tree");
780 DirectoryTreeFilterNode.OriginalNode imagesNodeOrig = dataSourcesFilterNode.getLookup().lookup(DirectoryTreeFilterNode.OriginalNode.class);
782 if (imagesNodeOrig == null) {
783 LOGGER.log(Level.SEVERE,
"Cannot find data sources node, won't refresh the content tree");
787 Node imagesNode = imagesNodeOrig.getNode();
804 private void setSelectedNode(
final String[] previouslySelectedNodePath,
final String rootNodeName) {
805 if (previouslySelectedNodePath == null) {
808 SwingUtilities.invokeLater(
new Runnable() {
811 if (previouslySelectedNodePath.length > 0 && (rootNodeName == null || previouslySelectedNodePath[0].equals(rootNodeName))) {
812 Node selectedNode = null;
813 ArrayList<String> selectedNodePath =
new ArrayList<>(Arrays.asList(previouslySelectedNodePath));
814 while (null == selectedNode && !selectedNodePath.isEmpty()) {
816 selectedNode = NodeOp.findPath(em.getRootContext(), selectedNodePath.toArray(
new String[0]));
817 }
catch (NodeNotFoundException ex) {
819 if (selectedNodePath.size() > 1) {
820 selectedNodePath.remove(selectedNodePath.size() - 1);
822 StringBuilder nodePath =
new StringBuilder();
823 for (
int i = 0; i < previouslySelectedNodePath.length; ++i) {
824 nodePath.append(previouslySelectedNodePath[i]).append(
"/");
826 LOGGER.log(Level.WARNING,
"Failed to find any nodes to select on path " + nodePath.toString(), ex);
832 if (null != selectedNode) {
833 if (rootNodeName != null) {
839 em.setExploredContextAndSelection(selectedNode,
new Node[]{selectedNode});
840 }
catch (PropertyVetoException ex) {
841 LOGGER.log(Level.WARNING,
"Property veto from ExplorerManager setting selection to " + selectedNode.getName(), ex);
861 int typeID = art.getArtifactTypeID();
862 String typeName = art.getArtifactTypeName();
863 Children rootChilds = em.getRootContext().getChildren();
864 Node treeNode = null;
866 Children resultsChilds = resultsNode.getChildren();
867 if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) {
868 Node hashsetRootNode = resultsChilds.findChild(typeName);
869 Children hashsetRootChilds = hashsetRootNode.getChildren();
871 String setName = null;
872 List<BlackboardAttribute> attributes = art.getAttributes();
873 for (BlackboardAttribute att : attributes) {
874 int typeId = att.getAttributeType().getTypeID();
875 if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
876 setName = att.getValueString();
879 treeNode = hashsetRootChilds.findChild(setName);
880 }
catch (TskException ex) {
881 LOGGER.log(Level.WARNING,
"Error retrieving attributes", ex);
883 }
else if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
884 Node keywordRootNode = resultsChilds.findChild(typeName);
885 Children keywordRootChilds = keywordRootNode.getChildren();
887 String listName = null;
888 String keywordName = null;
889 List<BlackboardAttribute> attributes = art.getAttributes();
890 for (BlackboardAttribute att : attributes) {
891 int typeId = att.getAttributeType().getTypeID();
892 if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
893 listName = att.getValueString();
894 }
else if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) {
895 keywordName = att.getValueString();
898 Node listNode = keywordRootChilds.findChild(listName);
899 if (listNode == null) {
902 Children listChildren = listNode.getChildren();
903 if (listChildren == null) {
906 treeNode = listChildren.findChild(keywordName);
907 }
catch (TskException ex) {
908 LOGGER.log(Level.WARNING,
"Error retrieving attributes", ex);
910 }
else if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID()
911 || typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
912 Node interestingItemsRootNode = resultsChilds.findChild(typeName);
913 Children interestingItemsRootChildren = interestingItemsRootNode.getChildren();
915 String setName = null;
916 List<BlackboardAttribute> attributes = art.getAttributes();
917 for (BlackboardAttribute att : attributes) {
918 int typeId = att.getAttributeType().getTypeID();
919 if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
920 setName = att.getValueString();
923 treeNode = interestingItemsRootChildren.findChild(setName);
924 }
catch (TskException ex) {
925 LOGGER.log(Level.WARNING,
"Error retrieving attributes", ex);
929 Children extractedChilds = extractedContent.getChildren();
930 if (extractedChilds == null) {
933 treeNode = extractedChilds.findChild(typeName);
936 if (treeNode == null) {
941 em.setExploredContextAndSelection(treeNode,
new Node[]{treeNode});
942 }
catch (PropertyVetoException ex) {
943 LOGGER.log(Level.WARNING,
"Property Veto: ", ex);
947 EventQueue.invokeLater(
new Runnable() {
950 Children resultChilds = dataResult.
getRootNode().getChildren();
951 Node select = resultChilds.findChild(Long.toString(art.getArtifactID()));
952 if (select != null) {
953 dataResult.requestActive();
955 fireViewerComplete();
964 NbBundle.getMessage(
this.getClass(),
"DirectoryTreeTopComponent.action.viewArtContent.text"),
973 void fireViewerComplete() {
977 }
catch (Exception e) {
978 LOGGER.log(Level.SEVERE,
"DirectoryTreeTopComponent listener threw exception", e);
979 MessageNotifyUtil.Notify.show(NbBundle.getMessage(
this.getClass(),
"DirectoryTreeTopComponent.moduleErr"),
980 NbBundle.getMessage(
this.getClass(),
981 "DirectoryTreeTopComponent.moduleErr.msg"),
982 MessageNotifyUtil.MessageType.ERROR);
List< Content > getDataSources()
TopComponent getTopComponent()
void viewArtifact(final BlackboardArtifact art)
static final String HIDE_SLACK_FILES_IN_VIEWS_TREE
final DataResultTopComponent dataResult
static SelectionContext getSelectionContext(Node n)
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)
static final Logger LOGGER
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
static final String HIDE_SLACK_FILES_IN_DATA_SOURCES_TREE
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)
void refreshDataSourceTree()
Action newToggleShowRejectedAction()
ExplorerManager getExplorerManager()
javax.swing.JButton backButton
SleuthkitCase getSleuthkitCase()
static synchronized boolean coreComponentsAreActive()
static SelectionContext getSelectionContext(Node n)
static DirectoryTreeTopComponent instance
void addOnFinishedListener(PropertyChangeListener l)
void addIngestModuleEventListener(final PropertyChangeListener listener)
static boolean isEmptyMimeTypeNode(Node node)
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)