19 package org.sleuthkit.autopsy.communications.relationships;
 
   21 import java.awt.Component;
 
   22 import java.awt.Cursor;
 
   23 import java.awt.KeyboardFocusManager;
 
   24 import java.beans.PropertyChangeEvent;
 
   25 import java.beans.PropertyChangeListener;
 
   26 import java.util.HashSet;
 
   27 import java.util.List;
 
   29 import java.util.concurrent.ExecutionException;
 
   30 import java.util.logging.Level;
 
   31 import java.util.stream.Collectors;
 
   32 import javax.swing.JOptionPane;
 
   33 import javax.swing.JPanel;
 
   34 import static javax.swing.SwingUtilities.isDescendingFrom;
 
   35 import javax.swing.SwingWorker;
 
   36 import org.openide.explorer.ExplorerManager;
 
   37 import static org.openide.explorer.ExplorerUtils.createLookup;
 
   38 import org.openide.nodes.AbstractNode;
 
   39 import org.openide.nodes.Node;
 
   40 import org.openide.util.Lookup;
 
   41 import org.openide.util.NbBundle.Messages;
 
   51 import static org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT;
 
   59 final 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;
 
   71     private MediaViewerWorker worker;
 
   72     private SelectionWorker selectionWorker;
 
   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();
 
  102     public String getDisplayName() {
 
  103         return Bundle.MediaViewer_Name();
 
  107     public JPanel getPanel() {
 
  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);
 
  124         worker = 
new MediaViewerWorker(info);
 
  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));
 
  203                 selectionWorker = 
new SelectionWorker(thumbnail);
 
  204                 selectionWorker.execute();
 
  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));
 
  264             selectionInfo = info;
 
  269             Set<Content> relationshipSources;
 
  270             Set<BlackboardArtifact> artifactList = 
new HashSet<>();
 
  272             if (selectionInfo != null) {
 
  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();
 
  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()
 
Set< Account > getAccounts()