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.PropertyChangeSupport;
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;
89 private final transient ExplorerManager
em =
new ExplorerManager();
92 "DirectoryTreeTopComponent.title.text"));
95 private static final String
PREFERRED_ID =
"DirectoryTreeTopComponent";
96 private final PropertyChangeSupport
pcs;
107 ((BeanTreeView)
jScrollPane1).setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
109 putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE);
114 associateLookup(ExplorerUtils.createLookup(em, getActionMap()));
116 this.pcs =
new PropertyChangeSupport(
this);
119 this.backList =
new LinkedList<>();
120 this.forwardList =
new LinkedList<>();
131 public void preferenceChange(PreferenceChangeEvent evt) {
132 switch (evt.getKey()) {
143 this.em.addPropertyChangeListener(
this);
149 this.dataResult.requestActive();
153 this.dataResult.
open();
175 backButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_back.png")));
179 backButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_back_disabled.png")));
180 backButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
181 backButton.setMaximumSize(
new java.awt.Dimension(55, 100));
182 backButton.setMinimumSize(
new java.awt.Dimension(5, 5));
183 backButton.setPreferredSize(
new java.awt.Dimension(23, 23));
184 backButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_back_hover.png")));
185 backButton.addActionListener(
new java.awt.event.ActionListener() {
186 public void actionPerformed(java.awt.event.ActionEvent evt) {
191 forwardButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_forward.png")));
195 forwardButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_forward_disabled.png")));
197 forwardButton.setMaximumSize(
new java.awt.Dimension(55, 100));
199 forwardButton.setPreferredSize(
new java.awt.Dimension(23, 23));
200 forwardButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_forward_hover.png")));
201 forwardButton.addActionListener(
new java.awt.event.ActionListener() {
202 public void actionPerformed(java.awt.event.ActionEvent evt) {
207 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
208 this.setLayout(layout);
209 layout.setHorizontalGroup(
210 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
211 .addGroup(layout.createSequentialGroup()
213 .addComponent(
backButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
215 .addComponent(
forwardButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
216 .addContainerGap(206, Short.MAX_VALUE))
217 .addComponent(
jSeparator1, javax.swing.GroupLayout.DEFAULT_SIZE, 262, Short.MAX_VALUE)
218 .addComponent(
jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 262, Short.MAX_VALUE)
220 layout.setVerticalGroup(
221 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
222 .addGroup(layout.createSequentialGroup()
223 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
224 .addComponent(
backButton, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
225 .addComponent(
forwardButton, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))
227 .addComponent(
jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 1, javax.swing.GroupLayout.PREFERRED_SIZE)
229 .addComponent(
jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 860, Short.MAX_VALUE)
236 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
239 String[] currentNodePath = backList.pollLast();
240 forwardList.addLast(currentNodePath);
248 String[] newCurrentNodePath = backList.peekLast();
251 if (backList.size() > 1) {
260 this.setCursor(null);
265 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
267 String[] newCurrentNodePath = forwardList.pollLast();
268 if (!forwardList.isEmpty()) {
274 backList.addLast(newCurrentNodePath);
280 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());
363 Node root =
new AbstractNode(contentChildren) {
370 return new Action[]{};
376 public Node.Handle getHandle() {
377 return new Node.Handle() {
379 public Node getNode()
throws IOException {
380 return em.getRootContext();
386 root =
new DirectoryTreeFilterNode(root,
true);
388 em.setRootContext(root);
389 em.getRootContext().setName(currentCase.
getName());
390 em.getRootContext().setDisplayName(currentCase.
getName());
391 ((BeanTreeView) this.
jScrollPane1).setRootVisible(
false);
396 Children childNodes = em.getRootContext().getChildren();
400 tree.expandNode(results);
402 Children resultsChilds = results.getChildren();
407 Children viewsChilds = views.getChildren();
408 for (Node n : viewsChilds.getNodes()) {
412 tree.collapseNode(views);
415 if (!dataResult.isOpened()) {
423 if (childNodes.getNodesCount() > 0) {
425 em.setSelectedNodes(
new Node[]{childNodes.getNodeAt(0)});
426 }
catch (Exception ex) {
427 logger.log(Level.SEVERE,
"Error setting default selected node.", ex);
434 this.setCursor(null);
447 contentChildren = null;
450 void writeProperties(java.util.Properties p) {
453 p.setProperty(
"version",
"1.0");
457 Object readProperties(java.util.Properties p) {
458 if (instance == null) {
466 String version = p.getProperty(
"version");
502 return new Action[]{};
514 if (selectedNodes.length > 0) {
515 result = selectedNodes[0];
529 String changed = evt.getPropertyName();
539 if (evt.getOldValue() != null && evt.getNewValue() == null) {
541 SwingUtilities.invokeLater(() -> {
542 Node emptyNode =
new AbstractNode(Children.LEAF);
543 em.setRootContext(emptyNode);
545 }
else if (evt.getNewValue() != null) {
547 Case newCase = (
Case) evt.getNewValue();
548 final String newCaseName = newCase.
getName();
549 SwingUtilities.invokeLater(() -> {
550 em.getRootContext().setName(newCaseName);
551 em.getRootContext().setDisplayName(newCaseName);
575 SwingUtilities.invokeLater(() -> {
579 }
catch (IllegalStateException | TskCoreException notUsed) {
585 else if (changed.equals(ExplorerManager.PROP_SELECTED_NODES)) {
586 SwingUtilities.invokeLater(() -> {
616 EventQueue.invokeLater(
new Runnable() {
624 if (treeNode != null) {
625 DirectoryTreeFilterNode.OriginalNode origin = treeNode.getLookup().lookup(DirectoryTreeFilterNode.OriginalNode.class);
626 if (origin == null) {
629 Node originNode = origin.getNode();
647 String displayName =
"";
648 Content content = originNode.getLookup().lookup(Content.class);
649 if (content != null) {
651 displayName = content.getUniquePath();
652 }
catch (TskCoreException ex) {
653 logger.log(Level.SEVERE,
"Exception while calling Content.getUniquePath() for node: " + originNode);
655 }
else if (originNode.getLookup().lookup(String.class) != null) {
656 displayName = originNode.getLookup().lookup(String.class);
658 dataResult.
setPath(displayName);
662 if (oldNodes != null && newNodes != null
663 && (oldNodes.length == newNodes.length)) {
664 boolean sameNodes =
true;
665 for (
int i = 0; i < oldNodes.length; i++) {
666 sameNodes = sameNodes && oldNodes[i].getName().equals(newNodes[i].getName());
669 dataResult.requestActive();
683 if (selectedNodes.length == 0) {
687 Node selectedNode = selectedNodes[0];
688 String selectedNodeName = selectedNode.getName();
696 String[] currentLast = backList.peekLast();
697 String lastNodeName = null;
698 if (currentLast != null) {
699 lastNodeName = currentLast[currentLast.length - 1];
702 if (currentLast == null || !selectedNodeName.equals(lastNodeName)) {
704 final String[] selectedPath = NodeOp.createPath(selectedNode, em.getRootContext());
705 backList.addLast(selectedPath);
706 if (backList.size() > 1) {
731 pcs.addPropertyChangeListener(listener);
736 pcs.removePropertyChangeListener(listener);
752 SwingUtilities.invokeLater(
new Runnable() {
765 final String[] selectedPath = NodeOp.createPath(selectedNode, em.getRootContext());
767 Children rootChildren = em.getRootContext().getChildren();
769 if (dataSourcesFilterNode == null) {
770 logger.log(Level.SEVERE,
"Cannot find data sources filter node, won't refresh the content tree");
773 DirectoryTreeFilterNode.OriginalNode imagesNodeOrig = dataSourcesFilterNode.getLookup().lookup(DirectoryTreeFilterNode.OriginalNode.class);
775 if (imagesNodeOrig == null) {
776 logger.log(Level.SEVERE,
"Cannot find data sources node, won't refresh the content tree");
780 Node imagesNode = imagesNodeOrig.getNode();
798 private void setSelectedNode(
final String[] previouslySelectedNodePath,
final String rootNodeName) {
799 if (previouslySelectedNodePath == null) {
802 SwingUtilities.invokeLater(
new Runnable() {
805 if (previouslySelectedNodePath.length > 0 && (rootNodeName == null || previouslySelectedNodePath[0].equals(rootNodeName))) {
806 Node selectedNode = null;
807 ArrayList<String> selectedNodePath =
new ArrayList<>(Arrays.asList(previouslySelectedNodePath));
808 while (null == selectedNode && !selectedNodePath.isEmpty()) {
810 selectedNode = NodeOp.findPath(em.getRootContext(), selectedNodePath.toArray(
new String[0]));
811 }
catch (NodeNotFoundException ex) {
813 if (selectedNodePath.size() > 1) {
814 selectedNodePath.remove(selectedNodePath.size() - 1);
816 StringBuilder nodePath =
new StringBuilder();
817 for (
int i = 0; i < previouslySelectedNodePath.length; ++i) {
818 nodePath.append(previouslySelectedNodePath[i]).append(
"/");
820 logger.log(Level.WARNING,
"Failed to find any nodes to select on path " + nodePath.toString(), ex);
826 if (null != selectedNode) {
827 if (rootNodeName != null) {
833 em.setExploredContextAndSelection(selectedNode,
new Node[]{selectedNode});
834 }
catch (PropertyVetoException ex) {
835 logger.log(Level.WARNING,
"Property veto from ExplorerManager setting selection to " + selectedNode.getName(), ex);
855 int typeID = art.getArtifactTypeID();
856 String typeName = art.getArtifactTypeName();
857 Children rootChilds = em.getRootContext().getChildren();
858 Node treeNode = null;
860 Children resultsChilds = resultsNode.getChildren();
861 if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) {
862 Node hashsetRootNode = resultsChilds.findChild(typeName);
863 Children hashsetRootChilds = hashsetRootNode.getChildren();
865 String setName = null;
866 List<BlackboardAttribute> attributes = art.getAttributes();
867 for (BlackboardAttribute att : attributes) {
868 int typeId = att.getAttributeType().getTypeID();
869 if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
870 setName = att.getValueString();
873 treeNode = hashsetRootChilds.findChild(setName);
874 }
catch (TskException ex) {
875 logger.log(Level.WARNING,
"Error retrieving attributes", ex);
877 }
else if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
878 Node keywordRootNode = resultsChilds.findChild(typeName);
879 Children keywordRootChilds = keywordRootNode.getChildren();
881 String listName = null;
882 String keywordName = null;
883 List<BlackboardAttribute> attributes = art.getAttributes();
884 for (BlackboardAttribute att : attributes) {
885 int typeId = att.getAttributeType().getTypeID();
886 if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
887 listName = att.getValueString();
888 }
else if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) {
889 keywordName = att.getValueString();
892 Node listNode = keywordRootChilds.findChild(listName);
893 if (listNode == null) {
896 Children listChildren = listNode.getChildren();
897 if (listChildren == null) {
900 treeNode = listChildren.findChild(keywordName);
901 }
catch (TskException ex) {
902 logger.log(Level.WARNING,
"Error retrieving attributes", ex);
904 }
else if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID()
905 || typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
906 Node interestingItemsRootNode = resultsChilds.findChild(typeName);
907 Children interestingItemsRootChildren = interestingItemsRootNode.getChildren();
909 String setName = null;
910 List<BlackboardAttribute> attributes = art.getAttributes();
911 for (BlackboardAttribute att : attributes) {
912 int typeId = att.getAttributeType().getTypeID();
913 if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
914 setName = att.getValueString();
917 treeNode = interestingItemsRootChildren.findChild(setName);
918 }
catch (TskException ex) {
919 logger.log(Level.WARNING,
"Error retrieving attributes", ex);
923 Children extractedChilds = extractedContent.getChildren();
924 if (extractedChilds == null) {
927 treeNode = extractedChilds.findChild(typeName);
930 if (treeNode == null) {
935 em.setExploredContextAndSelection(treeNode,
new Node[]{treeNode});
936 }
catch (PropertyVetoException ex) {
937 logger.log(Level.WARNING,
"Property Veto: ", ex);
941 EventQueue.invokeLater(
new Runnable() {
944 Children resultChilds = dataResult.
getRootNode().getChildren();
945 Node select = resultChilds.findChild(Long.toString(art.getArtifactID()));
946 if (select != null) {
947 dataResult.requestActive();
949 fireViewerComplete();
958 NbBundle.getMessage(
this.getClass(),
"DirectoryTreeTopComponent.action.viewArtContent.text"),
967 void fireViewerComplete() {
971 }
catch (Exception e) {
972 logger.log(Level.SEVERE,
"DirectoryTreeTopComponent listener threw exception", e);
973 MessageNotifyUtil.Notify.show(NbBundle.getMessage(
this.getClass(),
"DirectoryTreeTopComponent.moduleErr"),
974 NbBundle.getMessage(
this.getClass(),
975 "DirectoryTreeTopComponent.moduleErr.msg"),
976 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
static synchronized IngestManager getInstance()
DataResultTopComponent getDirectoryListing()
final LinkedList< String[]> forwardList
void setDirectoryListingActive()
final transient ExplorerManager em
RootContentChildren contentChildren
static boolean existsCurrentCase()
javax.swing.JSeparator jSeparator1
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
final PropertyChangeSupport pcs
DirectoryTreeTopComponent()
static synchronized DirectoryTreeTopComponent getDefault()
static final String PREFERRED_ID
javax.swing.JButton forwardButton
void addIngestJobEventListener(final PropertyChangeListener listener)
synchronized void addPropertyChangeListener(PropertyChangeListener listener)
void refreshContentKeys()
void viewArtifactContent(BlackboardArtifact art)
static boolean coreComponentsAreActive()
void refreshDataSourceTree()
ExplorerManager getExplorerManager()
javax.swing.JButton backButton
SleuthkitCase getSleuthkitCase()
static SelectionContext getSelectionContext(Node n)
static DirectoryTreeTopComponent instance
void addOnFinishedListener(PropertyChangeListener l)
synchronized void removePropertyChangeListener(PropertyChangeListener listener)
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)