Autopsy  4.19.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
DataArtifactContentViewer.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2020 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.corecomponents;
20 
21 import java.awt.Component;
22 import java.awt.Cursor;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.List;
26 import java.util.concurrent.ExecutionException;
27 import java.util.logging.Level;
28 import javax.swing.SwingWorker;
29 import org.openide.nodes.Node;
30 import org.openide.util.Lookup;
31 import org.openide.util.NbBundle;
32 import org.openide.util.lookup.ServiceProvider;
35 import org.sleuthkit.datamodel.BlackboardAttribute;
36 import org.sleuthkit.datamodel.Content;
37 import org.sleuthkit.datamodel.TskCoreException;
38 import org.sleuthkit.datamodel.TskException;
39 import java.util.Collections;
40 import java.util.HashSet;
45 import org.sleuthkit.datamodel.AnalysisResult;
46 import org.sleuthkit.datamodel.BlackboardArtifact;
47 import org.sleuthkit.datamodel.DataArtifact;
48 
56 @ServiceProvider(service = DataContentViewer.class, position = 6)
57 @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
58 public class DataArtifactContentViewer extends javax.swing.JPanel implements DataContentViewer {
59 
60  private static final long serialVersionUID = 1L;
61 
62  @NbBundle.Messages({
63  "DataArtifactContentViewer.failedToGetSourcePath.message=Failed to get source file path from case database",
64  "DataArtifactContentViewer.failedToGetAttributes.message=Failed to get some or all attributes from case database"
65  })
66  private final static Logger logger = Logger.getLogger(DataArtifactContentViewer.class.getName());
67  private final static String WAIT_TEXT = NbBundle.getMessage(DataArtifactContentViewer.class, "DataArtifactContentViewer.waitText");
68  private final static String ERROR_TEXT = NbBundle.getMessage(DataArtifactContentViewer.class, "DataArtifactContentViewer.errorText");
69 
70  // Value to return in isPreferred if this viewer is less preferred.
71  private static final int LESS_PREFERRED = 3;
72  // Value to return in isPreferred if this viewer is more preferred.
73  private static final int MORE_PREFERRED = 6;
74 
75  private Node currentNode; // @@@ Remove this when the redundant setNode() calls problem is fixed.
76  private int currentPage = 1;
77  private final Object lock = new Object();
78  private List<DataArtifact> artifactTableContents; // Accessed by multiple threads, use getArtifactContents() and setArtifactContents()
79  private SwingWorker<ViewUpdate, Void> currentTask; // Accessed by multiple threads, use startNewTask()
80 
81  private final Collection<ArtifactContentViewer> knowArtifactViewers = new HashSet<>(Lookup.getDefault().lookupAll(ArtifactContentViewer.class));
82 
84 
85  initComponents();
86 
87  resetComponents();
88  }
89 
95  @SuppressWarnings("unchecked")
96  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
97  private void initComponents() {
98  java.awt.GridBagConstraints gridBagConstraints;
99 
100  scrollPane = new javax.swing.JScrollPane();
101  menuBar = new javax.swing.JPanel();
102  totalPageLabel = new javax.swing.JLabel();
103  ofLabel = new javax.swing.JLabel();
104  currentPageLabel = new javax.swing.JLabel();
105  pageLabel = new javax.swing.JLabel();
106  nextPageButton = new javax.swing.JButton();
107  pageLabel2 = new javax.swing.JLabel();
108  prevPageButton = new javax.swing.JButton();
109  artifactLabel = new javax.swing.JLabel();
110  filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
111  artifactContentPanel = new javax.swing.JPanel();
112 
113  setMinimumSize(new java.awt.Dimension(300, 60));
114  setPreferredSize(new java.awt.Dimension(300, 60));
115 
116  scrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
117  scrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
118  scrollPane.setPreferredSize(new java.awt.Dimension(6, 60));
119 
120  menuBar.setMaximumSize(null);
121  menuBar.setMinimumSize(null);
122  menuBar.setPreferredSize(null);
123  menuBar.setLayout(new java.awt.GridBagLayout());
124 
125  totalPageLabel.setText(org.openide.util.NbBundle.getMessage(DataArtifactContentViewer.class, "DataArtifactContentViewer.totalPageLabel.text")); // NOI18N
126  totalPageLabel.setMaximumSize(null);
127  totalPageLabel.setPreferredSize(null);
128  gridBagConstraints = new java.awt.GridBagConstraints();
129  gridBagConstraints.gridx = 3;
130  gridBagConstraints.gridy = 0;
131  gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
132  gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
133  gridBagConstraints.insets = new java.awt.Insets(3, 12, 0, 0);
134  menuBar.add(totalPageLabel, gridBagConstraints);
135 
136  ofLabel.setText(org.openide.util.NbBundle.getMessage(DataArtifactContentViewer.class, "DataArtifactContentViewer.ofLabel.text")); // NOI18N
137  gridBagConstraints = new java.awt.GridBagConstraints();
138  gridBagConstraints.gridx = 2;
139  gridBagConstraints.gridy = 0;
140  gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
141  gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
142  gridBagConstraints.insets = new java.awt.Insets(3, 12, 0, 0);
143  menuBar.add(ofLabel, gridBagConstraints);
144 
145  currentPageLabel.setText(org.openide.util.NbBundle.getMessage(DataArtifactContentViewer.class, "DataArtifactContentViewer.currentPageLabel.text")); // NOI18N
146  currentPageLabel.setMaximumSize(null);
147  currentPageLabel.setPreferredSize(null);
148  gridBagConstraints = new java.awt.GridBagConstraints();
149  gridBagConstraints.gridx = 1;
150  gridBagConstraints.gridy = 0;
151  gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
152  gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
153  gridBagConstraints.insets = new java.awt.Insets(3, 7, 0, 0);
154  menuBar.add(currentPageLabel, gridBagConstraints);
155 
156  pageLabel.setText(org.openide.util.NbBundle.getMessage(DataArtifactContentViewer.class, "DataArtifactContentViewer.pageLabel.text")); // NOI18N
157  gridBagConstraints = new java.awt.GridBagConstraints();
158  gridBagConstraints.gridx = 0;
159  gridBagConstraints.gridy = 0;
160  gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
161  gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
162  gridBagConstraints.insets = new java.awt.Insets(3, 12, 0, 0);
163  menuBar.add(pageLabel, gridBagConstraints);
164 
165  nextPageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png"))); // NOI18N
166  nextPageButton.setText(org.openide.util.NbBundle.getMessage(DataArtifactContentViewer.class, "DataArtifactContentViewer.nextPageButton.text")); // NOI18N
167  nextPageButton.setBorderPainted(false);
168  nextPageButton.setContentAreaFilled(false);
169  nextPageButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward_disabled.png"))); // NOI18N
170  nextPageButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
171  nextPageButton.setPreferredSize(new java.awt.Dimension(23, 23));
172  nextPageButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png"))); // NOI18N
173  nextPageButton.addActionListener(new java.awt.event.ActionListener() {
174  public void actionPerformed(java.awt.event.ActionEvent evt) {
175  nextPageButtonActionPerformed(evt);
176  }
177  });
178  gridBagConstraints = new java.awt.GridBagConstraints();
179  gridBagConstraints.gridx = 6;
180  gridBagConstraints.gridy = 0;
181  gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
182  gridBagConstraints.insets = new java.awt.Insets(0, 0, 35, 0);
183  menuBar.add(nextPageButton, gridBagConstraints);
184 
185  pageLabel2.setText(org.openide.util.NbBundle.getMessage(DataArtifactContentViewer.class, "DataArtifactContentViewer.pageLabel2.text")); // NOI18N
186  pageLabel2.setMaximumSize(new java.awt.Dimension(29, 14));
187  pageLabel2.setMinimumSize(new java.awt.Dimension(29, 14));
188  gridBagConstraints = new java.awt.GridBagConstraints();
189  gridBagConstraints.gridx = 4;
190  gridBagConstraints.gridy = 0;
191  gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
192  gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
193  gridBagConstraints.insets = new java.awt.Insets(3, 30, 0, 0);
194  menuBar.add(pageLabel2, gridBagConstraints);
195 
196  prevPageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back.png"))); // NOI18N
197  prevPageButton.setText(org.openide.util.NbBundle.getMessage(DataArtifactContentViewer.class, "DataArtifactContentViewer.prevPageButton.text")); // NOI18N
198  prevPageButton.setBorderPainted(false);
199  prevPageButton.setContentAreaFilled(false);
200  prevPageButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back_disabled.png"))); // NOI18N
201  prevPageButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
202  prevPageButton.setPreferredSize(new java.awt.Dimension(23, 23));
203  prevPageButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png"))); // NOI18N
204  prevPageButton.addActionListener(new java.awt.event.ActionListener() {
205  public void actionPerformed(java.awt.event.ActionEvent evt) {
206  prevPageButtonActionPerformed(evt);
207  }
208  });
209  gridBagConstraints = new java.awt.GridBagConstraints();
210  gridBagConstraints.gridx = 5;
211  gridBagConstraints.gridy = 0;
212  gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
213  gridBagConstraints.insets = new java.awt.Insets(0, 5, 35, 0);
214  menuBar.add(prevPageButton, gridBagConstraints);
215  gridBagConstraints = new java.awt.GridBagConstraints();
216  gridBagConstraints.gridx = 8;
217  gridBagConstraints.gridy = 0;
218  gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
219  gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
220  gridBagConstraints.insets = new java.awt.Insets(3, 0, 0, 8);
221  menuBar.add(artifactLabel, gridBagConstraints);
222  gridBagConstraints = new java.awt.GridBagConstraints();
223  gridBagConstraints.gridx = 7;
224  gridBagConstraints.gridy = 0;
225  gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
226  gridBagConstraints.weightx = 0.1;
227  menuBar.add(filler1, gridBagConstraints);
228 
229  scrollPane.setViewportView(menuBar);
230 
231  artifactContentPanel.setLayout(new javax.swing.OverlayLayout(artifactContentPanel));
232 
233  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
234  this.setLayout(layout);
235  layout.setHorizontalGroup(
236  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
237  .addComponent(scrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
238  .addComponent(artifactContentPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
239  );
240  layout.setVerticalGroup(
241  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
242  .addGroup(layout.createSequentialGroup()
243  .addComponent(scrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
244  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
245  .addComponent(artifactContentPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 30, Short.MAX_VALUE))
246  );
247  }// </editor-fold>//GEN-END:initComponents
248 
249  private void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextPageButtonActionPerformed
250  currentPage += 1;
251  currentPageLabel.setText(Integer.toString(currentPage));
252  artifactLabel.setText(artifactTableContents.get(currentPage - 1).getDisplayName());
253  startNewTask(new SelectedArtifactChangedTask(currentPage));
254  }//GEN-LAST:event_nextPageButtonActionPerformed
255 
256  private void prevPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_prevPageButtonActionPerformed
257  currentPage -= 1;
258  currentPageLabel.setText(Integer.toString(currentPage));
259  artifactLabel.setText(artifactTableContents.get(currentPage - 1).getDisplayName());
260  startNewTask(new SelectedArtifactChangedTask(currentPage));
261  }//GEN-LAST:event_prevPageButtonActionPerformed
262 
263  // Variables declaration - do not modify//GEN-BEGIN:variables
264  private javax.swing.JPanel artifactContentPanel;
265  private javax.swing.JLabel artifactLabel;
266  private javax.swing.JLabel currentPageLabel;
267  private javax.swing.Box.Filler filler1;
268  private javax.swing.JPanel menuBar;
269  private javax.swing.JButton nextPageButton;
270  private javax.swing.JLabel ofLabel;
271  private javax.swing.JLabel pageLabel;
272  private javax.swing.JLabel pageLabel2;
273  private javax.swing.JButton prevPageButton;
274  private javax.swing.JScrollPane scrollPane;
275  private javax.swing.JLabel totalPageLabel;
276  // End of variables declaration//GEN-END:variables
277 
281  private void resetComponents() {
282  currentPage = 1;
283  currentPageLabel.setText("");
284  artifactLabel.setText("");
285  totalPageLabel.setText("");
286 
287  prevPageButton.setEnabled(false);
288  nextPageButton.setEnabled(false);
289  currentNode = null;
290 
291  artifactContentPanel.removeAll();
292  }
293 
294  @Override
295  public void setNode(Node selectedNode) {
296  currentNode = null;
297 
298  // Make sure there is a node. Null might be passed to reset the viewer.
299  if (selectedNode == null) {
300  return;
301  }
302 
303  // Make sure the node is of the correct type.
304  Lookup lookup = selectedNode.getLookup();
305  Content content = lookup.lookup(Content.class);
306  if (content == null) {
307  return;
308  }
309 
310  startNewTask(new SelectedNodeChangedTask(selectedNode));
311  }
312 
313  @Override
314  public String getTitle() {
315  return NbBundle.getMessage(this.getClass(), "DataArtifactContentViewer.title");
316  }
317 
318  @Override
319  public String getToolTip() {
320  return NbBundle.getMessage(this.getClass(), "DataArtifactContentViewer.toolTip");
321  }
322 
323  @Override
324  public DataContentViewer createInstance() {
325  return new DataArtifactContentViewer();
326  }
327 
328  @Override
329  public Component getComponent() {
330  return this;
331  }
332 
333  @Override
334  public void resetComponent() {
335  resetComponents();
336  }
337 
338  @Override
339  public boolean isSupported(Node node) {
340  if (node == null) {
341  return false;
342  }
343 
344  for (Content content : node.getLookup().lookupAll(Content.class)) {
345  if ((content != null) && (!(content instanceof DataArtifact)) && (!(content instanceof AnalysisResult))) {
346  try {
347  return Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard().hasDataArtifacts(content.getId());
348  } catch (NoCurrentCaseException | TskException ex) {
349  logger.log(Level.SEVERE, "Couldn't get count of DataArtifacts for content", ex); //NON-NLS
350  }
351  }
352  }
353 
354  return false;
355  }
356 
357  @Override
358  public int isPreferred(Node node) {
359  // get the artifact from the lookup
360  DataArtifact artifact = node.getLookup().lookup(DataArtifact.class);
361  if (artifact == null) {
362  return LESS_PREFERRED;
363  }
364 
365  // get the type of the artifact
366  BlackboardArtifact.Type artifactType;
367  try {
368  artifactType = artifact.getType();
369  } catch (TskCoreException ex) {
370  logger.log(Level.SEVERE,
371  String.format("There was an error getting the artifact type for artifact with id: %d", artifact.getId()),
372  ex);
373  return LESS_PREFERRED;
374  }
375 
376  // if web download or web cache, less preferred since the content is important and not the artifact itself.
377  if (artifactType.getTypeID() == BlackboardArtifact.Type.TSK_WEB_DOWNLOAD.getTypeID()
378  || artifactType.getTypeID() == BlackboardArtifact.Type.TSK_WEB_CACHE.getTypeID()) {
379 
380  return LESS_PREFERRED;
381  }
382 
383  switch (artifactType.getCategory()) {
384  // data artifacts should be more preferred
385  case DATA_ARTIFACT:
386  return MORE_PREFERRED;
387  // everything else is less preferred
388  default:
389  return LESS_PREFERRED;
390  }
391  }
392 
393  private ArtifactContentViewer getSupportingViewer(DataArtifact artifact) {
394  for (ArtifactContentViewer viewer : knowArtifactViewers) {
395  if (viewer.isSupported(artifact)) {
396  return viewer;
397  }
398  }
400  }
401 
406  private class ViewUpdate {
407 
408  int numberOfPages;
409  int currentPage;
410  DataArtifact artifact;
411  String errorMsg;
412 
413  ViewUpdate(int numberOfPages, int currentPage, DataArtifact artifact) {
414  this.currentPage = currentPage;
415  this.numberOfPages = numberOfPages;
416  this.artifact = artifact;
417  this.errorMsg = null;
418  }
419 
420  ViewUpdate(int numberOfPages, int currentPage, String errorMsg) {
421  this.currentPage = currentPage;
422  this.numberOfPages = numberOfPages;
423  this.errorMsg = errorMsg;
424  this.artifact = null;
425  }
426  }
427 
435  private void updateView(ViewUpdate viewUpdate) {
436  this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
437 
438  nextPageButton.setEnabled(viewUpdate.currentPage < viewUpdate.numberOfPages);
439  prevPageButton.setEnabled(viewUpdate.currentPage > 1);
440  currentPage = viewUpdate.currentPage;
441  totalPageLabel.setText(Integer.toString(viewUpdate.numberOfPages));
442  currentPageLabel.setText(Integer.toString(currentPage));
443 
444  artifactContentPanel.removeAll();
445 
446  if (viewUpdate.artifact != null) {
447  artifactLabel.setText(viewUpdate.artifact.getDisplayName());
448 
449  DataArtifact artifact = viewUpdate.artifact;
450  ArtifactContentViewer viewer = this.getSupportingViewer(artifact);
451  viewer.setArtifact(artifact);
452 
453  artifactContentPanel.add(viewer.getComponent());
454  } else {
455  artifactLabel.setText(viewUpdate.errorMsg);
456  }
457 
458  artifactContentPanel.repaint();
459  artifactContentPanel.revalidate();
460  this.setCursor(null);
461 
462  this.revalidate();
463  }
464 
471  private synchronized void startNewTask(SwingWorker<ViewUpdate, Void> task) {
472 
473  // The output of the previous task is no longer relevant.
474  if (currentTask != null) {
475  // This call sets a cancellation flag. It does not terminate the background thread running the task.
476  // The task must check the cancellation flag and react appropriately.
477  currentTask.cancel(false);
478  }
479 
480  // Start the new task.
481  currentTask = task;
482  currentTask.execute();
483  }
484 
491  private void setArtifactContents(List<DataArtifact> artifactList) {
492  synchronized (lock) {
493  this.artifactTableContents = artifactList;
494  }
495  }
496 
502  private List<DataArtifact> getArtifactContents() {
503  synchronized (lock) {
504  return Collections.unmodifiableList(artifactTableContents);
505  }
506  }
507 
513  private static boolean isSourceContent(Content content) {
514  return (content != null) &&
515  (!(content instanceof DataArtifact)) &&
516  (!(content instanceof AnalysisResult));
517  }
518 
524  private class SelectedNodeChangedTask extends SwingWorker<ViewUpdate, Void> {
525 
526  private final Node selectedNode;
527 
528  SelectedNodeChangedTask(Node selectedNode) {
529  this.selectedNode = selectedNode;
530  }
531 
532  @Override
534  // Get the lookup for the node for access to its underlying content and
535  // blackboard artifact, if any.
536  Lookup lookup = selectedNode.getLookup();
537 
538  // Get the content. We may get DataArtifacts, ignore those here.
539  List<DataArtifact> artifacts = Collections.emptyList();
540  Collection<? extends Content> contents = lookup.lookupAll(Content.class);
541  if (contents.isEmpty()) {
542  return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT);
543  }
544  for (Content content : contents) {
545  if (isSourceContent(content)) {
546  // Get all of the blackboard artifacts associated with the content. These are what this
547  // viewer displays.
548  try {
549  artifacts = content.getAllDataArtifacts();
550  break;
551  } catch (TskException ex) {
552  logger.log(Level.SEVERE, "Couldn't get artifacts", ex); //NON-NLS
553  return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT);
554  }
555  }
556  }
557 
558  if (isCancelled()) {
559  return null;
560  }
561 
562  // Build the new artifact contents cache.
563  ArrayList<DataArtifact> artifactContents = new ArrayList<>();
564  for (DataArtifact artifact : artifacts) {
565  artifactContents.add(artifact);
566  }
567 
568  // If the node has an underlying data artifact, show it. If not,
569  // show the first artifact.
570  int index = 0;
571  DataArtifact artifact = lookup.lookup(DataArtifact.class);
572  if (artifact != null) {
573  index = artifacts.indexOf(artifact);
574  if (index == -1) {
575  index = 0;
576  } else {
577  // if the artifact has an ASSOCIATED ARTIFACT, then we display the associated artifact instead
578  try {
579  for (BlackboardAttribute attr : artifact.getAttributes()) {
580  if (attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
581  long assocArtifactId = attr.getValueLong();
582  int assocArtifactIndex = -1;
583  for (DataArtifact art : artifacts) {
584  if (assocArtifactId == art.getArtifactID()) {
585  assocArtifactIndex = artifacts.indexOf(art);
586  break;
587  }
588  }
589  if (assocArtifactIndex >= 0) {
590  index = assocArtifactIndex;
591  }
592  break;
593  }
594  }
595  } catch (TskCoreException ex) {
596  logger.log(Level.WARNING, "Couldn't get associated artifact to display in Content Viewer.", ex); //NON-NLS
597  }
598  }
599 
600  }
601 
602  if (isCancelled()) {
603  return null;
604  }
605 
606  // Add one to the index of the artifact content for the corresponding page index.
607  ViewUpdate viewUpdate = new ViewUpdate(artifactContents.size(), index + 1, artifactContents.get(index));
608 
609  // It may take a considerable amount of time to fetch the attributes of the selected artifact
610  if (isCancelled()) {
611  return null;
612  }
613 
614  // Update the artifact contents cache.
615  setArtifactContents(artifactContents);
616 
617  return viewUpdate;
618  }
619 
620  @Override
621  protected void done() {
622  if (!isCancelled()) {
623  try {
624  ViewUpdate viewUpdate = get();
625  if (viewUpdate != null) {
626  currentNode = selectedNode;
627  updateView(viewUpdate);
628  }
629  } catch (InterruptedException | ExecutionException ex) {
630  logger.log(Level.WARNING, "Artifact display task unexpectedly interrupted or failed", ex); //NON-NLS
631  }
632  }
633  }
634  }
635 
641  private class SelectedArtifactChangedTask extends SwingWorker<ViewUpdate, Void> {
642 
643  private final int pageIndex;
644 
645  SelectedArtifactChangedTask(final int pageIndex) {
646  this.pageIndex = pageIndex;
647  }
648 
649  @Override
651  // Get the artifact content to display from the cache. Note that one must be subtracted from the
652  // page index to get the corresponding artifact content index.
653  List<DataArtifact> artifactContents = getArtifactContents();
654 
655  // It may take a considerable amount of time to fetch the attributes of the selected artifact so check for cancellation.
656  if (isCancelled()) {
657  return null;
658  }
659 
660  DataArtifact artifactContent = artifactContents.get(pageIndex - 1);
661  return new ViewUpdate(artifactContents.size(), pageIndex, artifactContent);
662  }
663 
664  @Override
665  protected void done() {
666  if (!isCancelled()) {
667  try {
668  ViewUpdate viewUpdate = get();
669  if (viewUpdate != null) {
670  updateView(viewUpdate);
671  }
672  } catch (InterruptedException | ExecutionException ex) {
673  logger.log(Level.WARNING, "Artifact display task unexpectedly interrupted or failed", ex); //NON-NLS
674  }
675  }
676  }
677  }
678 }
synchronized void startNewTask(SwingWorker< ViewUpdate, Void > task)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124

Copyright © 2012-2021 Basis Technology. Generated on: Fri Aug 6 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.