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.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.JPanel;
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;
86 private transient ExplorerManager
em =
new ExplorerManager();
89 "DirectoryTreeTopComponent.title.text"));
96 private static final String
PREFERRED_ID =
"DirectoryTreeTopComponent";
97 private PropertyChangeSupport
pcs;
111 ((BeanTreeView)
jScrollPane1).setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
113 putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE);
118 associateLookup(ExplorerUtils.createLookup(em, getActionMap()));
121 this.pcs =
new PropertyChangeSupport(
this);
124 this.backList =
new LinkedList<>();
125 this.forwardList =
new LinkedList<>();
136 public void preferenceChange(PreferenceChangeEvent evt) {
137 switch (evt.getKey()) {
148 this.em.addPropertyChangeListener(
this);
154 this.dataResult.requestActive();
158 this.dataResult.
open();
180 backButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_back.png")));
184 backButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_back_disabled.png")));
185 backButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
186 backButton.setMaximumSize(
new java.awt.Dimension(55, 100));
187 backButton.setMinimumSize(
new java.awt.Dimension(5, 5));
188 backButton.setPreferredSize(
new java.awt.Dimension(23, 23));
189 backButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_back_hover.png")));
190 backButton.addActionListener(
new java.awt.event.ActionListener() {
191 public void actionPerformed(java.awt.event.ActionEvent evt) {
196 forwardButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_forward.png")));
200 forwardButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_forward_disabled.png")));
202 forwardButton.setMaximumSize(
new java.awt.Dimension(55, 100));
204 forwardButton.setPreferredSize(
new java.awt.Dimension(23, 23));
205 forwardButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_forward_hover.png")));
206 forwardButton.addActionListener(
new java.awt.event.ActionListener() {
207 public void actionPerformed(java.awt.event.ActionEvent evt) {
212 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
213 this.setLayout(layout);
214 layout.setHorizontalGroup(
215 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
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 .addContainerGap(206, Short.MAX_VALUE))
222 .addComponent(
jSeparator1, javax.swing.GroupLayout.DEFAULT_SIZE, 262, Short.MAX_VALUE)
223 .addComponent(
jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 262, Short.MAX_VALUE)
225 layout.setVerticalGroup(
226 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
227 .addGroup(layout.createSequentialGroup()
228 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
229 .addComponent(
backButton, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
230 .addComponent(
forwardButton, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))
232 .addComponent(
jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 1, javax.swing.GroupLayout.PREFERRED_SIZE)
234 .addComponent(
jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 860, Short.MAX_VALUE)
241 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
244 String[] currentNodePath = backList.pollLast();
245 forwardList.addLast(currentNodePath);
251 String[] newCurrentNodePath = backList.peekLast();
254 if (backList.size() > 1) {
263 this.setCursor(null);
268 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
270 String[] newCurrentNodePath = forwardList.pollLast();
271 if (!forwardList.isEmpty()) {
277 backList.addLast(newCurrentNodePath);
283 this.setCursor(null);
299 if (instance == null) {
310 WindowManager winManager = WindowManager.
getDefault();
311 TopComponent win = winManager.findTopComponent(PREFERRED_ID);
314 "Cannot find " + PREFERRED_ID +
" component. It will not be located properly in the window system.");
318 return (DirectoryTreeTopComponent) win;
321 "There seem to be multiple components with the '" + PREFERRED_ID
322 +
"' ID. That is a potential source of errors and unexpected behavior.");
334 return TopComponent.PERSISTENCE_NEVER;
347 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
353 if (currentCase.
hasData() ==
false) {
355 ((BeanTreeView) this.
jScrollPane1).setRootVisible(
false);
358 List<Object> items =
new ArrayList<>();
361 items.add(
new Views(tskCase));
362 items.add(
new Results(tskCase));
363 items.add(
new Tags());
366 Node root =
new AbstractNode(contentChildren) {
373 return new Action[]{};
379 public Node.Handle getHandle() {
380 return new Node.Handle() {
382 public Node getNode()
throws IOException {
383 return em.getRootContext();
389 root =
new DirectoryTreeFilterNode(root,
true);
392 em.setRootContext(root);
393 em.getRootContext().setName(currentCase.
getName());
394 em.getRootContext().setDisplayName(currentCase.
getName());
395 ((BeanTreeView) this.
jScrollPane1).setRootVisible(
false);
400 Children childNodes = em.getRootContext().getChildren();
404 tree.expandNode(results);
406 Children resultsChilds = results.getChildren();
412 Children viewsChilds = views.getChildren();
413 for (Node n : viewsChilds.getNodes()) {
417 tree.collapseNode(views);
420 if (!dataResult.isOpened()) {
429 if (childNodes.getNodesCount() > 0) {
431 em.setSelectedNodes(
new Node[]{childNodes.getNodeAt(0)});
432 }
catch (Exception ex) {
433 logger.log(Level.SEVERE,
"Error setting default selected node.", ex);
440 this.setCursor(null);
453 contentChildren = null;
456 void writeProperties(java.util.Properties p) {
459 p.setProperty(
"version",
"1.0");
463 Object readProperties(java.util.Properties p) {
464 if (instance == null) {
472 String version = p.getProperty(
"version");
508 return new Action[]{};
520 if (selectedNodes.length > 0) {
521 result = selectedNodes[0];
534 String changed = evt.getPropertyName();
535 Object oldValue = evt.getOldValue();
536 Object newValue = evt.getNewValue();
541 String oldCaseName = oldValue.toString();
542 String newCaseName = newValue.toString();
546 if ((!oldCaseName.equals(
"")) && (!newCaseName.equals(
""))) {
548 em.getRootContext().setName(newCaseName);
549 em.getRootContext().setDisplayName(newCaseName);
561 if (oldValue != null && newValue == null) {
563 Node emptyNode =
new AbstractNode(Children.LEAF);
564 em.setRootContext(emptyNode);
565 }
else if (newValue != null) {
579 else if (changed.equals(ExplorerManager.PROP_SELECTED_NODES)) {
587 SwingUtilities.invokeLater(
new Runnable() {
594 SwingUtilities.invokeLater(
new Runnable() {
624 EventQueue.invokeLater(
new Runnable() {
635 if (treeNode != null) {
636 DirectoryTreeFilterNode.OriginalNode origin = treeNode.getLookup().lookup(DirectoryTreeFilterNode.OriginalNode.class);
637 if (origin == null) {
640 Node originNode = origin.getNode();
647 String displayName =
"";
649 if (content != null) {
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();
695 String[] currentLast = backList.peekLast();
696 String lastNodeName = null;
697 if (currentLast != null) {
698 lastNodeName = currentLast[currentLast.length - 1];
701 if (currentLast == null || !selectedNodeName.equals(lastNodeName)) {
703 final String[] selectedPath = NodeOp.createPath(selectedNode, em.getRootContext());
704 backList.addLast(selectedPath);
705 if (backList.size() > 1) {
730 pcs.addPropertyChangeListener(listener);
735 pcs.removePropertyChangeListener(listener);
751 SwingUtilities.invokeLater(
new Runnable() {
764 final String[] selectedPath = NodeOp.createPath(selectedNode, em.getRootContext());
766 Children rootChildren = em.getRootContext().getChildren();
768 if (dataSourcesFilterNode == null) {
769 logger.log(Level.SEVERE,
"Cannot find data sources filter node, won't refresh the content tree");
772 DirectoryTreeFilterNode.OriginalNode imagesNodeOrig = dataSourcesFilterNode.getLookup().lookup(DirectoryTreeFilterNode.OriginalNode.class);
774 if (imagesNodeOrig == null) {
775 logger.log(Level.SEVERE,
"Cannot find data sources node, won't refresh the content tree");
779 Node imagesNode = imagesNodeOrig.getNode();
848 private void setSelectedNode(
final String[] previouslySelectedNodePath,
final String rootNodeName) {
849 if (previouslySelectedNodePath == null) {
852 SwingUtilities.invokeLater(
new Runnable() {
855 if (previouslySelectedNodePath.length > 0 && (rootNodeName == null || previouslySelectedNodePath[0].equals(rootNodeName))) {
856 Node selectedNode = null;
857 ArrayList<String> selectedNodePath =
new ArrayList<>(Arrays.asList(previouslySelectedNodePath));
858 while (null == selectedNode && !selectedNodePath.isEmpty()) {
860 selectedNode = NodeOp.findPath(em.getRootContext(), selectedNodePath.toArray(
new String[0]));
861 }
catch (NodeNotFoundException ex) {
863 if (selectedNodePath.size() > 1) {
864 selectedNodePath.remove(selectedNodePath.size() - 1);
866 StringBuilder nodePath =
new StringBuilder();
867 for (
int i = 0; i < previouslySelectedNodePath.length; ++i) {
868 nodePath.append(previouslySelectedNodePath[i]).append(
"/");
870 logger.log(Level.WARNING,
"Failed to find any nodes to select on path " + nodePath.toString(), ex);
876 if (null != selectedNode) {
877 if (rootNodeName != null) {
883 em.setExploredContextAndSelection(selectedNode,
new Node[]{selectedNode});
884 }
catch (PropertyVetoException ex) {
885 logger.log(Level.WARNING,
"Property veto from ExplorerManager setting selection to " + selectedNode.getName(), ex);
906 Children rootChilds = em.getRootContext().getChildren();
907 Node treeNode = null;
909 Children resultsChilds = resultsNode.getChildren();
911 Node hashsetRootNode = resultsChilds.findChild(type.getLabel());
912 Children hashsetRootChilds = hashsetRootNode.getChildren();
914 String setName = null;
917 int typeId = att.getAttributeTypeID();
919 setName = att.getValueString();
922 treeNode = hashsetRootChilds.findChild(setName);
924 logger.log(Level.WARNING,
"Error retrieving attributes", ex);
927 Node keywordRootNode = resultsChilds.findChild(type.getLabel());
928 Children keywordRootChilds = keywordRootNode.getChildren();
930 String listName = null;
931 String keywordName = null;
934 int typeId = att.getAttributeTypeID();
936 listName = att.getValueString();
938 keywordName = att.getValueString();
941 Node listNode = keywordRootChilds.findChild(listName);
942 if (listNode == null) {
945 Children listChildren = listNode.getChildren();
946 if (listChildren == null) {
949 treeNode = listChildren.findChild(keywordName);
951 logger.log(Level.WARNING,
"Error retrieving attributes", ex);
955 Node interestingItemsRootNode = resultsChilds.findChild(type.getLabel());
956 Children interestingItemsRootChildren = interestingItemsRootNode.getChildren();
958 String setName = null;
961 int typeId = att.getAttributeTypeID();
963 setName = att.getValueString();
966 treeNode = interestingItemsRootChildren.findChild(setName);
968 logger.log(Level.WARNING,
"Error retrieving attributes", ex);
972 Children extractedChilds = extractedContent.getChildren();
973 if (extractedChilds == null) {
976 treeNode = extractedChilds.findChild(type.getLabel());
979 if (treeNode == null) {
984 em.setExploredContextAndSelection(treeNode,
new Node[]{treeNode});
985 }
catch (PropertyVetoException ex) {
986 logger.log(Level.WARNING,
"Property Veto: ", ex);
990 EventQueue.invokeLater(
new Runnable() {
993 Children resultChilds = dataResult.
getRootNode().getChildren();
994 Node select = resultChilds.findChild(Long.toString(art.
getArtifactID()));
995 if (select != null) {
996 dataResult.requestActive();
998 fireViewerComplete();
1007 NbBundle.getMessage(
this.getClass(),
"DirectoryTreeTopComponent.action.viewArtContent.text"),
1020 void fireViewerComplete() {
1024 }
catch (Exception e) {
1025 logger.log(Level.SEVERE,
"DirectoryTreeTopComponent listener threw exception", e);
1026 MessageNotifyUtil.Notify.show(NbBundle.getMessage(
this.getClass(),
"DirectoryTreeTopComponent.moduleErr"),
1027 NbBundle.getMessage(
this.getClass(),
1028 "DirectoryTreeTopComponent.moduleErr.msg"),
1029 MessageNotifyUtil.MessageType.ERROR);
TSK_INTERESTING_ARTIFACT_HIT
TopComponent getTopComponent()
void viewArtifact(final BlackboardArtifact art)
static final Logger logger
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()
void setDirectoryListingActive()
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)
static ARTIFACT_TYPE fromID(int ID)
DataResultTopComponent dataResult
boolean hasMenuOpenAction()
void propertyChange(PropertyChangeEvent evt)
javax.swing.JScrollPane jScrollPane1
void updateHistory(Node[] selectedNodes)
void refreshContentKeys()
void openDirectoryListing()
void refreshContentTreeSafe()
void readPropertiesImpl(java.util.Properties p)
void backButtonActionPerformed(java.awt.event.ActionEvent evt)
static final String FINISHED_DISPLAY_EVT
transient ExplorerManager em
DirectoryTreeTopComponent()
static synchronized DirectoryTreeTopComponent getDefault()
static final String PREFERRED_ID
javax.swing.JButton forwardButton
void addIngestJobEventListener(final PropertyChangeListener listener)
synchronized void addPropertyChangeListener(PropertyChangeListener listener)
LinkedList< String[]> forwardList
void viewArtifactContent(BlackboardArtifact art)
void refreshDataSourceTree()
ExplorerManager getExplorerManager()
javax.swing.JButton backButton
SleuthkitCase getSleuthkitCase()
static SelectionContext getSelectionContext(Node n)
List< BlackboardAttribute > getAttributes()
static DirectoryTreeTopComponent instance
void addOnFinishedListener(PropertyChangeListener l)
synchronized void removePropertyChangeListener(PropertyChangeListener listener)
void addIngestModuleEventListener(final PropertyChangeListener listener)
static synchronized void addPropertyChangeListener(PropertyChangeListener listener)
static Case getCurrentCase()
static void addChangeListener(PreferenceChangeListener listener)
LinkedList< String[]> backList
void forwardButtonActionPerformed(java.awt.event.ActionEvent evt)
void setSelectedNodes(Node[] selected)
void subscribeToChangeEvents()
static synchronized DirectoryTreeTopComponent findInstance()
void setPath(String pathText)
static boolean isCaseOpen()
PropertyChangeSupport pcs
static Logger getLogger(String name)
void setNode(Node selectedNode)