19 package org.sleuthkit.autopsy.corecomponents;
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;
39 import java.util.Collections;
40 import java.util.HashSet;
56 @ServiceProvider(service = DataContentViewer.class, position = 6)
57 @SuppressWarnings(
"PMD.SingularField")
60 private static final long serialVersionUID = 1L;
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"
68 private final static String ERROR_TEXT = NbBundle.getMessage(
DataArtifactContentViewer.class,
"DataArtifactContentViewer.errorText");
71 private static final int LESS_PREFERRED = 3;
73 private static final int MORE_PREFERRED = 6;
76 private int currentPage = 1;
77 private final Object lock =
new Object();
81 private final Collection<ArtifactContentViewer> knowArtifactViewers =
new HashSet<>(Lookup.getDefault().lookupAll(
ArtifactContentViewer.class));
95 @SuppressWarnings(
"unchecked")
97 private
void initComponents() {
98 java.awt.GridBagConstraints gridBagConstraints;
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();
113 setMinimumSize(
new java.awt.Dimension(300, 60));
114 setPreferredSize(
new java.awt.Dimension(300, 60));
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));
120 menuBar.setMaximumSize(null);
121 menuBar.setMinimumSize(null);
122 menuBar.setPreferredSize(null);
123 menuBar.setLayout(
new java.awt.GridBagLayout());
125 totalPageLabel.setText(
org.openide.util.NbBundle.getMessage(
DataArtifactContentViewer.class,
"DataArtifactContentViewer.totalPageLabel.text"));
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);
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);
145 currentPageLabel.setText(
org.openide.util.NbBundle.getMessage(
DataArtifactContentViewer.class,
"DataArtifactContentViewer.currentPageLabel.text"));
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);
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);
165 nextPageButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png")));
166 nextPageButton.setText(
org.openide.util.NbBundle.getMessage(
DataArtifactContentViewer.class,
"DataArtifactContentViewer.nextPageButton.text"));
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")));
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")));
173 nextPageButton.addActionListener(
new java.awt.event.ActionListener() {
174 public void actionPerformed(java.awt.event.ActionEvent evt) {
175 nextPageButtonActionPerformed(evt);
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);
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);
196 prevPageButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_back.png")));
197 prevPageButton.setText(
org.openide.util.NbBundle.getMessage(
DataArtifactContentViewer.class,
"DataArtifactContentViewer.prevPageButton.text"));
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")));
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")));
204 prevPageButton.addActionListener(
new java.awt.event.ActionListener() {
205 public void actionPerformed(java.awt.event.ActionEvent evt) {
206 prevPageButtonActionPerformed(evt);
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);
229 scrollPane.setViewportView(menuBar);
231 artifactContentPanel.setLayout(
new javax.swing.OverlayLayout(artifactContentPanel));
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)
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))
251 currentPageLabel.setText(Integer.toString(currentPage));
252 artifactLabel.setText(artifactTableContents.get(currentPage - 1).getDisplayName());
258 currentPageLabel.setText(Integer.toString(currentPage));
259 artifactLabel.setText(artifactTableContents.get(currentPage - 1).getDisplayName());
283 currentPageLabel.setText(
"");
284 artifactLabel.setText(
"");
285 totalPageLabel.setText(
"");
287 prevPageButton.setEnabled(
false);
288 nextPageButton.setEnabled(
false);
291 artifactContentPanel.removeAll();
296 if (currentNode == selectedNode) {
299 currentNode = selectedNode;
302 if (selectedNode == null) {
307 Lookup lookup = selectedNode.getLookup();
308 Content content = lookup.lookup(Content.class);
309 if (content == null) {
318 return NbBundle.getMessage(this.getClass(),
"DataArtifactContentViewer.title");
323 return NbBundle.getMessage(this.getClass(),
"DataArtifactContentViewer.toolTip");
347 for (Content content : node.getLookup().lookupAll(Content.class)) {
348 if ((content != null) && (!(content instanceof DataArtifact)) && (!(content instanceof AnalysisResult))) {
352 logger.log(Level.SEVERE,
"Couldn't get count of DataArtifacts for content", ex);
363 DataArtifact artifact = node.getLookup().lookup(DataArtifact.class);
364 if (artifact == null) {
365 return LESS_PREFERRED;
369 BlackboardArtifact.Type artifactType;
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()),
376 return LESS_PREFERRED;
380 if (artifactType.getTypeID() == BlackboardArtifact.Type.TSK_WEB_DOWNLOAD.getTypeID()
381 || artifactType.getTypeID() == BlackboardArtifact.Type.TSK_WEB_CACHE.getTypeID()) {
383 return LESS_PREFERRED;
386 switch (artifactType.getCategory()) {
389 return MORE_PREFERRED;
391 case ANALYSIS_RESULT:
393 return LESS_PREFERRED;
399 if (viewer.isSupported(artifact)) {
414 DataArtifact artifact;
417 ViewUpdate(
int numberOfPages,
int currentPage, DataArtifact artifact) {
418 this.currentPage = currentPage;
419 this.numberOfPages = numberOfPages;
420 this.artifact = artifact;
421 this.errorMsg = null;
424 ViewUpdate(
int numberOfPages,
int currentPage, String errorMsg) {
425 this.currentPage = currentPage;
426 this.numberOfPages = numberOfPages;
427 this.errorMsg = errorMsg;
428 this.artifact = null;
440 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
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));
448 artifactContentPanel.removeAll();
450 if (viewUpdate.artifact != null) {
451 artifactLabel.setText(viewUpdate.artifact.getDisplayName());
453 DataArtifact artifact = viewUpdate.artifact;
459 artifactLabel.setText(viewUpdate.errorMsg);
462 artifactContentPanel.repaint();
463 artifactContentPanel.revalidate();
464 this.setCursor(null);
475 private synchronized void startNewTask(SwingWorker<ViewUpdate, Void> task) {
478 if (currentTask != null) {
481 currentTask.cancel(
false);
486 currentTask.execute();
496 synchronized (lock) {
497 this.artifactTableContents = artifactList;
507 synchronized (lock) {
508 return Collections.unmodifiableList(artifactTableContents);
518 return (content != null) &&
519 (!(content instanceof DataArtifact)) &&
520 (!(content instanceof AnalysisResult));
533 this.selectedNode = selectedNode;
540 Lookup lookup = selectedNode.getLookup();
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);
548 for (Content content : contents) {
549 if (isSourceContent(content)) {
553 artifacts = content.getAllDataArtifacts();
555 }
catch (TskException ex) {
556 logger.log(Level.SEVERE,
"Couldn't get artifacts", ex);
557 return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT);
567 ArrayList<DataArtifact> artifactContents =
new ArrayList<>();
568 for (DataArtifact artifact : artifacts) {
569 artifactContents.add(artifact);
575 DataArtifact artifact = lookup.lookup(DataArtifact.class);
576 if (artifact != null) {
577 index = artifacts.indexOf(artifact);
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);
593 if (assocArtifactIndex >= 0) {
594 index = assocArtifactIndex;
599 }
catch (TskCoreException ex) {
600 logger.log(Level.WARNING,
"Couldn't get associated artifact to display in Content Viewer.", ex);
611 ViewUpdate viewUpdate =
new ViewUpdate(artifactContents.size(), index + 1, artifactContents.get(index));
619 setArtifactContents(artifactContents);
626 if (!isCancelled()) {
629 if (viewUpdate != null) {
630 updateView(viewUpdate);
632 }
catch (InterruptedException | ExecutionException ex) {
633 logger.log(Level.WARNING,
"Artifact display task unexpectedly interrupted or failed", ex);
649 this.pageIndex = pageIndex;
656 List<DataArtifact> artifactContents = getArtifactContents();
663 DataArtifact artifactContent = artifactContents.get(pageIndex - 1);
664 return new ViewUpdate(artifactContents.size(), pageIndex, artifactContent);
669 if (!isCancelled()) {
672 if (viewUpdate != null) {
673 updateView(viewUpdate);
675 }
catch (InterruptedException | ExecutionException ex) {
676 logger.log(Level.WARNING,
"Artifact display task unexpectedly interrupted or failed", ex);
ViewUpdate doInBackground()
int isPreferred(Node node)
DataArtifactContentViewer()
DataContentViewer createInstance()
List< DataArtifact > artifactTableContents
javax.swing.Box.Filler filler1
javax.swing.JLabel artifactLabel
void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt)
javax.swing.JLabel pageLabel2
javax.swing.JLabel currentPageLabel
javax.swing.JPanel menuBar
javax.swing.JLabel ofLabel
void updateView(ViewUpdate viewUpdate)
javax.swing.JScrollPane scrollPane
javax.swing.JButton prevPageButton
void setNode(Node selectedNode)
SleuthkitCase getSleuthkitCase()
void setArtifactContents(List< DataArtifact > artifactList)
synchronized void startNewTask(SwingWorker< ViewUpdate, Void > task)
javax.swing.JPanel artifactContentPanel
javax.swing.JButton nextPageButton
ViewUpdate doInBackground()
ArtifactContentViewer getSupportingViewer(DataArtifact artifact)
boolean isSupported(Node node)
synchronized static Logger getLogger(String name)
javax.swing.JLabel totalPageLabel
static Case getCurrentCaseThrows()
void prevPageButtonActionPerformed(java.awt.event.ActionEvent evt)
javax.swing.JLabel pageLabel
static boolean isSourceContent(Content content)
SwingWorker< ViewUpdate, Void > currentTask
void setArtifact(BlackboardArtifact artifact)
List< DataArtifact > getArtifactContents()