Autopsy  4.18.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  if (currentNode == selectedNode) {
297  return;
298  }
299  currentNode = selectedNode;
300 
301  // Make sure there is a node. Null might be passed to reset the viewer.
302  if (selectedNode == null) {
303  return;
304  }
305 
306  // Make sure the node is of the correct type.
307  Lookup lookup = selectedNode.getLookup();
308  Content content = lookup.lookup(Content.class);
309  if (content == null) {
310  return;
311  }
312 
313  startNewTask(new SelectedNodeChangedTask(selectedNode));
314  }
315 
316  @Override
317  public String getTitle() {
318  return NbBundle.getMessage(this.getClass(), "DataArtifactContentViewer.title");
319  }
320 
321  @Override
322  public String getToolTip() {
323  return NbBundle.getMessage(this.getClass(), "DataArtifactContentViewer.toolTip");
324  }
325 
326  @Override
327  public DataContentViewer createInstance() {
328  return new DataArtifactContentViewer();
329  }
330 
331  @Override
332  public Component getComponent() {
333  return this;
334  }
335 
336  @Override
337  public void resetComponent() {
338  resetComponents();
339  }
340 
341  @Override
342  public boolean isSupported(Node node) {
343  if (node == null) {
344  return false;
345  }
346 
347  for (Content content : node.getLookup().lookupAll(Content.class)) {
348  if ((content != null) && (!(content instanceof DataArtifact)) && (!(content instanceof AnalysisResult))) {
349  try {
350  return Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard().hasDataArtifacts(content.getId());
351  } catch (NoCurrentCaseException | TskException ex) {
352  logger.log(Level.SEVERE, "Couldn't get count of DataArtifacts for content", ex); //NON-NLS
353  }
354  }
355  }
356 
357  return false;
358  }
359 
360  @Override
361  public int isPreferred(Node node) {
362  // get the artifact from the lookup
363  DataArtifact artifact = node.getLookup().lookup(DataArtifact.class);
364  if (artifact == null) {
365  return LESS_PREFERRED;
366  }
367 
368  // get the type of the artifact
369  BlackboardArtifact.Type artifactType;
370  try {
371  artifactType = artifact.getType();
372  } catch (TskCoreException ex) {
373  logger.log(Level.SEVERE,
374  String.format("There was an error getting the artifact type for artifact with id: %d", artifact.getId()),
375  ex);
376  return LESS_PREFERRED;
377  }
378 
379  // if web download or web cache, less preferred since the content is important and not the artifact itself.
380  if (artifactType.getTypeID() == BlackboardArtifact.Type.TSK_WEB_DOWNLOAD.getTypeID()
381  || artifactType.getTypeID() == BlackboardArtifact.Type.TSK_WEB_CACHE.getTypeID()) {
382 
383  return LESS_PREFERRED;
384  }
385 
386  switch (artifactType.getCategory()) {
387  // data artifacts should be more preferred
388  case DATA_ARTIFACT:
389  return MORE_PREFERRED;
390  // everything else is less preferred
391  case ANALYSIS_RESULT:
392  default:
393  return LESS_PREFERRED;
394  }
395  }
396 
397  private ArtifactContentViewer getSupportingViewer(DataArtifact artifact) {
398  for (ArtifactContentViewer viewer : knowArtifactViewers) {
399  if (viewer.isSupported(artifact)) {
400  return viewer;
401  }
402  }
404  }
405 
410  private class ViewUpdate {
411 
412  int numberOfPages;
413  int currentPage;
414  DataArtifact artifact;
415  String errorMsg;
416 
417  ViewUpdate(int numberOfPages, int currentPage, DataArtifact artifact) {
418  this.currentPage = currentPage;
419  this.numberOfPages = numberOfPages;
420  this.artifact = artifact;
421  this.errorMsg = null;
422  }
423 
424  ViewUpdate(int numberOfPages, int currentPage, String errorMsg) {
425  this.currentPage = currentPage;
426  this.numberOfPages = numberOfPages;
427  this.errorMsg = errorMsg;
428  this.artifact = null;
429  }
430  }
431 
439  private void updateView(ViewUpdate viewUpdate) {
440  this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
441 
442  nextPageButton.setEnabled(viewUpdate.currentPage < viewUpdate.numberOfPages);
443  prevPageButton.setEnabled(viewUpdate.currentPage > 1);
444  currentPage = viewUpdate.currentPage;
445  totalPageLabel.setText(Integer.toString(viewUpdate.numberOfPages));
446  currentPageLabel.setText(Integer.toString(currentPage));
447 
448  artifactContentPanel.removeAll();
449 
450  if (viewUpdate.artifact != null) {
451  artifactLabel.setText(viewUpdate.artifact.getDisplayName());
452 
453  DataArtifact artifact = viewUpdate.artifact;
454  ArtifactContentViewer viewer = this.getSupportingViewer(artifact);
455  viewer.setArtifact(artifact);
456 
457  artifactContentPanel.add(viewer.getComponent());
458  } else {
459  artifactLabel.setText(viewUpdate.errorMsg);
460  }
461 
462  artifactContentPanel.repaint();
463  artifactContentPanel.revalidate();
464  this.setCursor(null);
465 
466  this.revalidate();
467  }
468 
475  private synchronized void startNewTask(SwingWorker<ViewUpdate, Void> task) {
476 
477  // The output of the previous task is no longer relevant.
478  if (currentTask != null) {
479  // This call sets a cancellation flag. It does not terminate the background thread running the task.
480  // The task must check the cancellation flag and react appropriately.
481  currentTask.cancel(false);
482  }
483 
484  // Start the new task.
485  currentTask = task;
486  currentTask.execute();
487  }
488 
495  private void setArtifactContents(List<DataArtifact> artifactList) {
496  synchronized (lock) {
497  this.artifactTableContents = artifactList;
498  }
499  }
500 
506  private List<DataArtifact> getArtifactContents() {
507  synchronized (lock) {
508  return Collections.unmodifiableList(artifactTableContents);
509  }
510  }
511 
517  private static boolean isSourceContent(Content content) {
518  return (content != null) &&
519  (!(content instanceof DataArtifact)) &&
520  (!(content instanceof AnalysisResult));
521  }
522 
528  private class SelectedNodeChangedTask extends SwingWorker<ViewUpdate, Void> {
529 
530  private final Node selectedNode;
531 
532  SelectedNodeChangedTask(Node selectedNode) {
533  this.selectedNode = selectedNode;
534  }
535 
536  @Override
538  // Get the lookup for the node for access to its underlying content and
539  // blackboard artifact, if any.
540  Lookup lookup = selectedNode.getLookup();
541 
542  // Get the content. We may get DataArtifacts, ignore those here.
543  List<DataArtifact> artifacts = Collections.emptyList();
544  Collection<? extends Content> contents = lookup.lookupAll(Content.class);
545  if (contents.isEmpty()) {
546  return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT);
547  }
548  for (Content content : contents) {
549  if (isSourceContent(content)) {
550  // Get all of the blackboard artifacts associated with the content. These are what this
551  // viewer displays.
552  try {
553  artifacts = content.getAllDataArtifacts();
554  break;
555  } catch (TskException ex) {
556  logger.log(Level.SEVERE, "Couldn't get artifacts", ex); //NON-NLS
557  return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT);
558  }
559  }
560  }
561 
562  if (isCancelled()) {
563  return null;
564  }
565 
566  // Build the new artifact contents cache.
567  ArrayList<DataArtifact> artifactContents = new ArrayList<>();
568  for (DataArtifact artifact : artifacts) {
569  artifactContents.add(artifact);
570  }
571 
572  // If the node has an underlying data artifact, show it. If not,
573  // show the first artifact.
574  int index = 0;
575  DataArtifact artifact = lookup.lookup(DataArtifact.class);
576  if (artifact != null) {
577  index = artifacts.indexOf(artifact);
578  if (index == -1) {
579  index = 0;
580  } else {
581  // if the artifact has an ASSOCIATED ARTIFACT, then we display the associated artifact instead
582  try {
583  for (BlackboardAttribute attr : artifact.getAttributes()) {
584  if (attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
585  long assocArtifactId = attr.getValueLong();
586  int assocArtifactIndex = -1;
587  for (DataArtifact art : artifacts) {
588  if (assocArtifactId == art.getArtifactID()) {
589  assocArtifactIndex = artifacts.indexOf(art);
590  break;
591  }
592  }
593  if (assocArtifactIndex >= 0) {
594  index = assocArtifactIndex;
595  }
596  break;
597  }
598  }
599  } catch (TskCoreException ex) {
600  logger.log(Level.WARNING, "Couldn't get associated artifact to display in Content Viewer.", ex); //NON-NLS
601  }
602  }
603 
604  }
605 
606  if (isCancelled()) {
607  return null;
608  }
609 
610  // Add one to the index of the artifact content for the corresponding page index.
611  ViewUpdate viewUpdate = new ViewUpdate(artifactContents.size(), index + 1, artifactContents.get(index));
612 
613  // It may take a considerable amount of time to fetch the attributes of the selected artifact
614  if (isCancelled()) {
615  return null;
616  }
617 
618  // Update the artifact contents cache.
619  setArtifactContents(artifactContents);
620 
621  return viewUpdate;
622  }
623 
624  @Override
625  protected void done() {
626  if (!isCancelled()) {
627  try {
628  ViewUpdate viewUpdate = get();
629  if (viewUpdate != null) {
630  updateView(viewUpdate);
631  }
632  } catch (InterruptedException | ExecutionException ex) {
633  logger.log(Level.WARNING, "Artifact display task unexpectedly interrupted or failed", ex); //NON-NLS
634  }
635  }
636  }
637  }
638 
644  private class SelectedArtifactChangedTask extends SwingWorker<ViewUpdate, Void> {
645 
646  private final int pageIndex;
647 
648  SelectedArtifactChangedTask(final int pageIndex) {
649  this.pageIndex = pageIndex;
650  }
651 
652  @Override
654  // Get the artifact content to display from the cache. Note that one must be subtracted from the
655  // page index to get the corresponding artifact content index.
656  List<DataArtifact> artifactContents = getArtifactContents();
657 
658  // It may take a considerable amount of time to fetch the attributes of the selected artifact so check for cancellation.
659  if (isCancelled()) {
660  return null;
661  }
662 
663  DataArtifact artifactContent = artifactContents.get(pageIndex - 1);
664  return new ViewUpdate(artifactContents.size(), pageIndex, artifactContent);
665  }
666 
667  @Override
668  protected void done() {
669  if (!isCancelled()) {
670  try {
671  ViewUpdate viewUpdate = get();
672  if (viewUpdate != null) {
673  updateView(viewUpdate);
674  }
675  } catch (InterruptedException | ExecutionException ex) {
676  logger.log(Level.WARNING, "Artifact display task unexpectedly interrupted or failed", ex); //NON-NLS
677  }
678  }
679  }
680  }
681 }
synchronized void startNewTask(SwingWorker< ViewUpdate, Void > task)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124

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