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();
299 if (selectedNode == null) {
304 Lookup lookup = selectedNode.getLookup();
305 Content content = lookup.lookup(Content.class);
306 if (content == null) {
315 return NbBundle.getMessage(this.getClass(),
"DataArtifactContentViewer.title");
320 return NbBundle.getMessage(this.getClass(),
"DataArtifactContentViewer.toolTip");
344 for (Content content : node.getLookup().lookupAll(Content.class)) {
345 if ((content != null) && (!(content instanceof DataArtifact)) && (!(content instanceof AnalysisResult))) {
349 logger.log(Level.SEVERE,
"Couldn't get count of DataArtifacts for content", ex);
360 DataArtifact artifact = node.getLookup().lookup(DataArtifact.class);
361 if (artifact == null) {
362 return LESS_PREFERRED;
366 BlackboardArtifact.Type artifactType;
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()),
373 return LESS_PREFERRED;
377 if (artifactType.getTypeID() == BlackboardArtifact.Type.TSK_WEB_DOWNLOAD.getTypeID()
378 || artifactType.getTypeID() == BlackboardArtifact.Type.TSK_WEB_CACHE.getTypeID()) {
380 return LESS_PREFERRED;
383 switch (artifactType.getCategory()) {
386 return MORE_PREFERRED;
389 return LESS_PREFERRED;
395 if (viewer.isSupported(artifact)) {
410 DataArtifact artifact;
413 ViewUpdate(
int numberOfPages,
int currentPage, DataArtifact artifact) {
414 this.currentPage = currentPage;
415 this.numberOfPages = numberOfPages;
416 this.artifact = artifact;
417 this.errorMsg = null;
420 ViewUpdate(
int numberOfPages,
int currentPage, String errorMsg) {
421 this.currentPage = currentPage;
422 this.numberOfPages = numberOfPages;
423 this.errorMsg = errorMsg;
424 this.artifact = null;
436 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
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));
444 artifactContentPanel.removeAll();
446 if (viewUpdate.artifact != null) {
447 artifactLabel.setText(viewUpdate.artifact.getDisplayName());
449 DataArtifact artifact = viewUpdate.artifact;
455 artifactLabel.setText(viewUpdate.errorMsg);
458 artifactContentPanel.repaint();
459 artifactContentPanel.revalidate();
460 this.setCursor(null);
471 private synchronized void startNewTask(SwingWorker<ViewUpdate, Void> task) {
474 if (currentTask != null) {
477 currentTask.cancel(
false);
482 currentTask.execute();
492 synchronized (lock) {
493 this.artifactTableContents = artifactList;
503 synchronized (lock) {
504 return Collections.unmodifiableList(artifactTableContents);
514 return (content != null) &&
515 (!(content instanceof DataArtifact)) &&
516 (!(content instanceof AnalysisResult));
529 this.selectedNode = selectedNode;
536 Lookup lookup = selectedNode.getLookup();
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);
544 for (Content content : contents) {
545 if (isSourceContent(content)) {
549 artifacts = content.getAllDataArtifacts();
551 }
catch (TskException ex) {
552 logger.log(Level.SEVERE,
"Couldn't get artifacts", ex);
553 return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT);
563 ArrayList<DataArtifact> artifactContents =
new ArrayList<>();
564 for (DataArtifact artifact : artifacts) {
565 artifactContents.add(artifact);
571 DataArtifact artifact = lookup.lookup(DataArtifact.class);
572 if (artifact != null) {
573 index = artifacts.indexOf(artifact);
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);
589 if (assocArtifactIndex >= 0) {
590 index = assocArtifactIndex;
595 }
catch (TskCoreException ex) {
596 logger.log(Level.WARNING,
"Couldn't get associated artifact to display in Content Viewer.", ex);
607 ViewUpdate viewUpdate =
new ViewUpdate(artifactContents.size(), index + 1, artifactContents.get(index));
615 setArtifactContents(artifactContents);
622 if (!isCancelled()) {
625 if (viewUpdate != null) {
626 currentNode = selectedNode;
627 updateView(viewUpdate);
629 }
catch (InterruptedException | ExecutionException ex) {
630 logger.log(Level.WARNING,
"Artifact display task unexpectedly interrupted or failed", ex);
646 this.pageIndex = pageIndex;
653 List<DataArtifact> artifactContents = getArtifactContents();
660 DataArtifact artifactContent = artifactContents.get(pageIndex - 1);
661 return new ViewUpdate(artifactContents.size(), pageIndex, artifactContent);
666 if (!isCancelled()) {
669 if (viewUpdate != null) {
670 updateView(viewUpdate);
672 }
catch (InterruptedException | ExecutionException ex) {
673 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()