19package org.sleuthkit.autopsy.communications.relationships;
21import java.awt.Component;
22import java.awt.Cursor;
23import java.awt.KeyboardFocusManager;
24import java.beans.PropertyChangeEvent;
25import java.beans.PropertyChangeListener;
26import java.util.HashSet;
29import java.util.concurrent.ExecutionException;
30import java.util.logging.Level;
31import java.util.stream.Collectors;
32import javax.swing.JOptionPane;
33import javax.swing.JPanel;
34import static javax.swing.SwingUtilities.isDescendingFrom;
35import javax.swing.SwingWorker;
36import org.openide.explorer.ExplorerManager;
37import static org.openide.explorer.ExplorerUtils.createLookup;
38import org.openide.nodes.AbstractNode;
39import org.openide.nodes.Node;
40import org.openide.util.Lookup;
41import org.openide.util.NbBundle.Messages;
42import org.sleuthkit.autopsy.casemodule.Case;
43import org.sleuthkit.autopsy.communications.ModifiableProxyLookup;
44import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
45import org.sleuthkit.autopsy.coreutils.Logger;
46import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
47import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
48import org.sleuthkit.datamodel.AbstractContent;
49import org.sleuthkit.datamodel.Account;
50import org.sleuthkit.datamodel.BlackboardArtifact;
51import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT;
52import org.sleuthkit.datamodel.BlackboardAttribute;
53import org.sleuthkit.datamodel.Content;
54import org.sleuthkit.datamodel.SleuthkitCase;
59final class MediaViewer
extends JPanel implements
RelationshipsViewer, ExplorerManager.Provider, Lookup.Provider {
61 private static final Logger logger = Logger.getLogger(MediaViewer.class.getName());
62 private static final long serialVersionUID = 1L;
64 private final ExplorerManager tableEM =
new ExplorerManager();
65 private PropertyChangeListener focusPropertyListener;
67 private final ModifiableProxyLookup proxyLookup;
69 private final MessageDataContent contentViewer;
75 "MediaViewer_Name=Media Attachments"
83 splitPane.setResizeWeight(0.5);
84 splitPane.setDividerLocation(0.5);
86 contentViewer =
new MessageDataContent();
87 contentViewer.setPreferredSize(
new java.awt.Dimension(450, 400));
88 splitPane.setRightComponent(contentViewer);
90 proxyLookup =
new ModifiableProxyLookup(createLookup(tableEM, getActionMap()));
92 tableEM.addPropertyChangeListener((PropertyChangeEvent evt) -> {
93 if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) {
94 handleNodeSelectionChange();
98 thumbnailViewer.resetComponent();
103 return Bundle.MediaViewer_Name();
112 public void setSelectionInfo(SelectionInfo info) {
113 contentViewer.setNode(
null);
114 thumbnailViewer.setNode(
null);
116 if (worker !=
null) {
120 if(selectionWorker !=
null) {
121 selectionWorker.cancel(
true);
126 setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
131 public ExplorerManager getExplorerManager() {
136 public Lookup getLookup() {
141 public void addNotify() {
144 if (focusPropertyListener ==
null) {
147 focusPropertyListener = (
final PropertyChangeEvent focusEvent) -> {
148 if (focusEvent.getPropertyName().equalsIgnoreCase(
"focusOwner")) {
149 handleFocusChange((Component) focusEvent.getNewValue());
155 KeyboardFocusManager.getCurrentKeyboardFocusManager()
156 .addPropertyChangeListener(
"focusOwner", focusPropertyListener);
164 private void handleFocusChange(Component newFocusOwner) {
165 if (newFocusOwner ==
null) {
168 if (isDescendingFrom(newFocusOwner, contentViewer)) {
170 proxyLookup.setNewLookups(createLookup(contentViewer.getExplorerManager(), getActionMap()));
171 }
else if (isDescendingFrom(newFocusOwner,
this)) {
173 proxyLookup.setNewLookups(createLookup(tableEM, getActionMap()));
179 public void removeNotify() {
180 super.removeNotify();
182 if (focusPropertyListener !=
null) {
183 KeyboardFocusManager.getCurrentKeyboardFocusManager()
184 .removePropertyChangeListener(
"focusOwner", focusPropertyListener);
191 private void handleNodeSelectionChange() {
192 final Node[] nodes = tableEM.getSelectedNodes();
193 contentViewer.setNode(
null);
195 if(selectionWorker !=
null) {
196 selectionWorker.cancel(
true);
199 if (nodes !=
null && nodes.length == 1) {
200 AbstractContent thumbnail = nodes[0].getLookup().lookup(AbstractContent.class);
201 if (thumbnail !=
null) {
202 setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
204 selectionWorker.execute();
212 private class SelectionWorker
extends SwingWorker<BlackboardArtifact, Void> {
217 SelectionWorker(AbstractContent
thumbnail) {
224 List<BlackboardArtifact> artifactsList = skCase.getBlackboardArtifacts(TSK_ASSOCIATED_OBJECT,
thumbnail.getId());
225 for (BlackboardArtifact contextArtifact : artifactsList) {
226 BlackboardAttribute associatedArtifactAttribute = contextArtifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
227 if (associatedArtifactAttribute !=
null) {
228 long artifactId = associatedArtifactAttribute.getValueLong();
229 return contextArtifact.getSleuthkitCase().getBlackboardArtifact(artifactId);
242 BlackboardArtifact artifact =
get();
243 if (artifact !=
null) {
246 contentViewer.setNode(
null);
248 }
catch (InterruptedException | ExecutionException ex) {
249 logger.log(Level.SEVERE,
"Failed message viewer based on thumbnail selection. thumbnailID = " +
thumbnail.getId(), ex);
251 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
259 private class MediaViewerWorker
extends SwingWorker<TableFilterNode, Void> {
269 Set<Content> relationshipSources;
270 Set<BlackboardArtifact> artifactList =
new HashSet<>();
273 relationshipSources =
selectionInfo.getRelationshipSources();
275 relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> {
276 artifactList.add((BlackboardArtifact) content);
284 "MediaViewer_selection_failure_msg=Failed to get media attachments for selected accounts.",
285 "MediaViewer_selection_failure_title=Selection Failed"
293 thumbnailViewer.setNode(
get());
294 }
catch (ExecutionException | InterruptedException ex) {
295 String accounts =
selectionInfo.getAccounts().stream().map(Account::getTypeSpecificID).collect(Collectors.joining(
","));
296 logger.log(Level.WARNING,
"Unable to update cvt media viewer for " + accounts, ex);
298 JOptionPane.showMessageDialog(MediaViewer.this, Bundle.MediaViewer_selection_failure_msg(), Bundle.MediaViewer_selection_failure_title(), JOptionPane.ERROR_MESSAGE);
300 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
311 @SuppressWarnings(
"unchecked")
313 private
void initComponents() {
314 java.awt.GridBagConstraints gridBagConstraints;
316 splitPane =
new javax.swing.JSplitPane();
317 thumbnailViewer =
new org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail(tableEM);
319 setLayout(
new java.awt.GridBagLayout());
321 splitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
323 thumbnailViewer.setMinimumSize(
new java.awt.Dimension(350, 102));
324 thumbnailViewer.setPreferredSize(
new java.awt.Dimension(450, 400));
325 splitPane.setLeftComponent(thumbnailViewer);
327 gridBagConstraints =
new java.awt.GridBagConstraints();
328 gridBagConstraints.gridx = 0;
329 gridBagConstraints.gridy = 0;
330 gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
331 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
332 gridBagConstraints.weightx = 1.0;
333 gridBagConstraints.weighty = 1.0;
334 add(splitPane, gridBagConstraints);
339 private javax.swing.JSplitPane splitPane;
SleuthkitCase getSleuthkitCase()
static Case getCurrentCase()