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

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.