diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.form b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.form
index fc3eb5b61f..610873d75f 100644
--- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.form
+++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.form
@@ -50,7 +50,7 @@
-
+
@@ -65,7 +65,7 @@
-
+
@@ -82,7 +82,14 @@
-
+
+
+
+
+
+
+
+
@@ -99,33 +106,20 @@
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -242,6 +236,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java
index c7226483ef..3ed728006b 100644
--- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java
+++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java
@@ -1,15 +1,15 @@
/*
* Autopsy Forensic Browser
- *
+ *
* Copyright 2011-2013 Basis Technology Corp.
* Contact: carrier sleuthkit org
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -18,32 +18,37 @@
*/
package org.sleuthkit.autopsy.corecomponents;
-import java.awt.*;
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.awt.datatransfer.StringSelection;
+import java.awt.event.KeyEvent;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import javax.swing.JMenuItem;
-import javax.swing.JTextPane;
+import javax.swing.KeyStroke;
import javax.swing.SwingWorker;
+import javax.swing.table.DefaultTableModel;
+import org.apache.commons.lang.StringUtils;
import org.openide.nodes.Node;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
-import org.sleuthkit.autopsy.casemodule.Case;
-import org.sleuthkit.autopsy.contentviewers.Utilities;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
import org.sleuthkit.autopsy.coreutils.Logger;
-import org.sleuthkit.autopsy.datamodel.ArtifactStringContent;
+import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.Content;
-import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskException;
+import org.netbeans.swing.etable.ETable;
/**
* Instances of this class display the BlackboardArtifacts associated with the
@@ -53,21 +58,57 @@ import org.sleuthkit.datamodel.TskException;
@ServiceProvider(service = DataContentViewer.class, position = 3)
public class DataContentViewerArtifact extends javax.swing.JPanel implements DataContentViewer {
+ @NbBundle.Messages({
+ "DataContentViewerArtifact.attrsTableHeader.type=Type",
+ "DataContentViewerArtifact.attrsTableHeader.value=Value",
+ "DataContentViewerArtifact.attrsTableHeader.sources=Source(s)",
+ "DataContentViewerArtifact.failedToGetSourcePath.message=Failed to get source file path from case database",
+ "DataContentViewerArtifact.failedToGetAttributes.message=Failed to get some or all attributes from case database"
+ })
private final static Logger logger = Logger.getLogger(DataContentViewerArtifact.class.getName());
private final static String WAIT_TEXT = NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.waitText");
private final static String ERROR_TEXT = NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.errorText");
private Node currentNode; // @@@ Remove this when the redundant setNode() calls problem is fixed.
private int currentPage = 1;
private final Object lock = new Object();
- private List artifactContentStrings; // Accessed by multiple threads, use getArtifactContentStrings() and setArtifactContentStrings()
+ private List artifactTableContents; // Accessed by multiple threads, use getArtifactContents() and setArtifactContents()
SwingWorker currentTask; // Accessed by multiple threads, use startNewTask()
+ private static final String[] COLUMN_HEADERS = {
+ Bundle.DataContentViewerArtifact_attrsTableHeader_type(),
+ Bundle.DataContentViewerArtifact_attrsTableHeader_value(),
+ Bundle.DataContentViewerArtifact_attrsTableHeader_sources()};
public DataContentViewerArtifact() {
+ initResultsTable();
initComponents();
+ resultsTableScrollPane.setViewportView(resultsTable);
customizeComponents();
resetComponents();
}
+ private void initResultsTable() {
+ resultsTable = new ETable();
+ resultsTable.setModel(new javax.swing.table.DefaultTableModel() {
+ private static final long serialVersionUID = 1L;
+
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return false;
+ }
+ });
+ resultsTable.setCellSelectionEnabled(true);
+ resultsTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION);
+ updateColumnSizes();
+ }
+
+ private void updateColumnSizes() {
+ resultsTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_NEXT_COLUMN);
+ if (resultsTable.getColumnModel().getColumnCount() > 0) {
+ resultsTable.getColumnModel().getColumn(0).setPreferredWidth(100);
+ resultsTable.getColumnModel().getColumn(1).setPreferredWidth(800);
+ resultsTable.getColumnModel().getColumn(2).setPreferredWidth(100);
+ }
+ }
+
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
@@ -81,175 +122,191 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
copyMenuItem = new javax.swing.JMenuItem();
selectAllMenuItem = new javax.swing.JMenuItem();
jPanel1 = new javax.swing.JPanel();
- jScrollPane1 = new javax.swing.JScrollPane();
- outputViewPane = new JTextPane(){
- public boolean getScrollableTracksViewportWidth() {
- return (getSize().width < 400);
- }};
- totalPageLabel = new javax.swing.JLabel();
- ofLabel = new javax.swing.JLabel();
- currentPageLabel = new javax.swing.JLabel();
- pageLabel = new javax.swing.JLabel();
- nextPageButton = new javax.swing.JButton();
- pageLabel2 = new javax.swing.JLabel();
- prevPageButton = new javax.swing.JButton();
+ totalPageLabel = new javax.swing.JLabel();
+ ofLabel = new javax.swing.JLabel();
+ currentPageLabel = new javax.swing.JLabel();
+ pageLabel = new javax.swing.JLabel();
+ nextPageButton = new javax.swing.JButton();
+ pageLabel2 = new javax.swing.JLabel();
+ prevPageButton = new javax.swing.JButton();
+ resultsTableScrollPane = new javax.swing.JScrollPane();
+ artifactLabel = new javax.swing.JLabel();
- copyMenuItem.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.copyMenuItem.text")); // NOI18N
- rightClickMenu.add(copyMenuItem);
+ copyMenuItem.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.copyMenuItem.text")); // NOI18N
+ rightClickMenu.add(copyMenuItem);
- selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.selectAllMenuItem.text")); // NOI18N
- rightClickMenu.add(selectAllMenuItem);
+ selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.selectAllMenuItem.text")); // NOI18N
+ rightClickMenu.add(selectAllMenuItem);
- setPreferredSize(new java.awt.Dimension(622, 424));
+ setPreferredSize(new java.awt.Dimension(622, 424));
- jPanel1.setPreferredSize(new java.awt.Dimension(622, 424));
+ jPanel1.setPreferredSize(new java.awt.Dimension(622, 424));
- outputViewPane.setEditable(false);
- outputViewPane.setPreferredSize(new java.awt.Dimension(700, 400));
- jScrollPane1.setViewportView(outputViewPane);
+ totalPageLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.totalPageLabel.text")); // NOI18N
- totalPageLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.totalPageLabel.text")); // NOI18N
+ ofLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.ofLabel.text")); // NOI18N
- ofLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.ofLabel.text")); // NOI18N
+ currentPageLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.currentPageLabel.text")); // NOI18N
+ currentPageLabel.setMaximumSize(new java.awt.Dimension(18, 14));
+ currentPageLabel.setMinimumSize(new java.awt.Dimension(18, 14));
+ currentPageLabel.setPreferredSize(new java.awt.Dimension(18, 14));
- currentPageLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.currentPageLabel.text")); // NOI18N
- currentPageLabel.setMaximumSize(new java.awt.Dimension(18, 14));
- currentPageLabel.setMinimumSize(new java.awt.Dimension(18, 14));
- currentPageLabel.setPreferredSize(new java.awt.Dimension(18, 14));
+ pageLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.pageLabel.text")); // NOI18N
+ pageLabel.setMaximumSize(new java.awt.Dimension(33, 14));
+ pageLabel.setMinimumSize(new java.awt.Dimension(33, 14));
+ pageLabel.setPreferredSize(new java.awt.Dimension(33, 14));
- pageLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.pageLabel.text")); // NOI18N
- pageLabel.setMaximumSize(new java.awt.Dimension(33, 14));
- pageLabel.setMinimumSize(new java.awt.Dimension(33, 14));
- pageLabel.setPreferredSize(new java.awt.Dimension(33, 14));
+ nextPageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png"))); // NOI18N
+ nextPageButton.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.nextPageButton.text")); // NOI18N
+ nextPageButton.setBorderPainted(false);
+ nextPageButton.setContentAreaFilled(false);
+ nextPageButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward_disabled.png"))); // NOI18N
+ nextPageButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
+ nextPageButton.setPreferredSize(new java.awt.Dimension(23, 23));
+ nextPageButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png"))); // NOI18N
+ nextPageButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ nextPageButtonActionPerformed(evt);
+ }
+ });
- nextPageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png"))); // NOI18N NON-NLS
- nextPageButton.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.nextPageButton.text")); // NOI18N
- nextPageButton.setBorderPainted(false);
- nextPageButton.setContentAreaFilled(false);
- nextPageButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward_disabled.png"))); // NOI18N NON-NLS
- nextPageButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
- nextPageButton.setPreferredSize(new java.awt.Dimension(23, 23));
- nextPageButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png"))); // NOI18N NON-NLS
- nextPageButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- nextPageButtonActionPerformed(evt);
- }
- });
+ pageLabel2.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.pageLabel2.text")); // NOI18N
+ pageLabel2.setMaximumSize(new java.awt.Dimension(29, 14));
+ pageLabel2.setMinimumSize(new java.awt.Dimension(29, 14));
+ pageLabel2.setPreferredSize(new java.awt.Dimension(29, 14));
- pageLabel2.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.pageLabel2.text")); // NOI18N
- pageLabel2.setMaximumSize(new java.awt.Dimension(29, 14));
- pageLabel2.setMinimumSize(new java.awt.Dimension(29, 14));
- pageLabel2.setPreferredSize(new java.awt.Dimension(29, 14));
+ prevPageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back.png"))); // NOI18N
+ prevPageButton.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.prevPageButton.text")); // NOI18N
+ prevPageButton.setBorderPainted(false);
+ prevPageButton.setContentAreaFilled(false);
+ prevPageButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back_disabled.png"))); // NOI18N
+ prevPageButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
+ prevPageButton.setPreferredSize(new java.awt.Dimension(23, 23));
+ prevPageButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png"))); // NOI18N
+ prevPageButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ prevPageButtonActionPerformed(evt);
+ }
+ });
- prevPageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back.png"))); // NOI18N NON-NLS
- prevPageButton.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.prevPageButton.text")); // NOI18N
- prevPageButton.setBorderPainted(false);
- prevPageButton.setContentAreaFilled(false);
- prevPageButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back_disabled.png"))); // NOI18N NON-NLS
- prevPageButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
- prevPageButton.setPreferredSize(new java.awt.Dimension(23, 23));
- prevPageButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png"))); // NOI18N NON-NLS
- prevPageButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- prevPageButtonActionPerformed(evt);
- }
- });
-
- javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
- jPanel1.setLayout(jPanel1Layout);
- jPanel1Layout.setHorizontalGroup(
- jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(jPanel1Layout.createSequentialGroup()
- .addContainerGap()
- .addComponent(pageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(currentPageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addComponent(ofLabel)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addComponent(totalPageLabel)
- .addGap(41, 41, 41)
- .addComponent(pageLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 38, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addGap(0, 0, 0)
+ javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
+ jPanel1.setLayout(jPanel1Layout);
+ jPanel1Layout.setHorizontalGroup(
+ jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(pageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(currentPageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(ofLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(totalPageLabel)
+ .addGap(41, 41, 41)
+ .addComponent(pageLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 38, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(0, 0, 0)
+ .addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap(366, Short.MAX_VALUE))
+ .addComponent(resultsTableScrollPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 622, Short.MAX_VALUE)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
+ .addContainerGap(280, Short.MAX_VALUE)
+ .addComponent(artifactLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 258, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap(84, Short.MAX_VALUE)))
+ );
+ jPanel1Layout.setVerticalGroup(
+ jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(pageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(currentPageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(ofLabel)
+ .addComponent(totalPageLabel))
.addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addContainerGap(366, Short.MAX_VALUE))
- .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 622, Short.MAX_VALUE)
- );
- jPanel1Layout.setVerticalGroup(
- jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(pageLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(resultsTableScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 394, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(0, 0, 0))
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
- .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(pageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addComponent(currentPageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addComponent(ofLabel)
- .addComponent(totalPageLabel))
- .addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addComponent(pageLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addGap(0, 0, 0)
- .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 401, Short.MAX_VALUE))
- );
+ .addComponent(artifactLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(0, 401, Short.MAX_VALUE)))
+ );
- javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
- this.setLayout(layout);
- layout.setHorizontalGroup(
- layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- );
- layout.setVerticalGroup(
- layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- );
- }// //GEN-END:initComponents
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ );
+ }// //GEN-END:initComponents
private void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextPageButtonActionPerformed
currentPage = currentPage + 1;
currentPageLabel.setText(Integer.toString(currentPage));
+ artifactLabel.setText(artifactTableContents.get(currentPage - 1).getArtifactDisplayName());
startNewTask(new SelectedArtifactChangedTask(currentPage));
}//GEN-LAST:event_nextPageButtonActionPerformed
private void prevPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_prevPageButtonActionPerformed
currentPage = currentPage - 1;
currentPageLabel.setText(Integer.toString(currentPage));
+ artifactLabel.setText(artifactTableContents.get(currentPage - 1).getArtifactDisplayName());
startNewTask(new SelectedArtifactChangedTask(currentPage));
}//GEN-LAST:event_prevPageButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JLabel artifactLabel;
private javax.swing.JMenuItem copyMenuItem;
private javax.swing.JLabel currentPageLabel;
private javax.swing.JPanel jPanel1;
- private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JButton nextPageButton;
private javax.swing.JLabel ofLabel;
- private javax.swing.JTextPane outputViewPane;
private javax.swing.JLabel pageLabel;
private javax.swing.JLabel pageLabel2;
private javax.swing.JButton prevPageButton;
+ private javax.swing.JScrollPane resultsTableScrollPane;
private javax.swing.JPopupMenu rightClickMenu;
private javax.swing.JMenuItem selectAllMenuItem;
private javax.swing.JLabel totalPageLabel;
// End of variables declaration//GEN-END:variables
+ private ETable resultsTable;
private void customizeComponents() {
- outputViewPane.setComponentPopupMenu(rightClickMenu);
+ resultsTable.setComponentPopupMenu(rightClickMenu);
ActionListener actList = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JMenuItem jmi = (JMenuItem) e.getSource();
if (jmi.equals(copyMenuItem)) {
- outputViewPane.copy();
+ StringBuilder selectedText = new StringBuilder(512);
+ for (int row : resultsTable.getSelectedRows()) {
+ for (int col : resultsTable.getSelectedColumns()) {
+ selectedText.append((String) resultsTable.getValueAt(row, col));
+ selectedText.append("\t");
+ }
+ //if its the last row selected don't add a new line
+ if (row != resultsTable.getSelectedRows()[resultsTable.getSelectedRows().length - 1]) {
+ selectedText.append(System.lineSeparator());
+ }
+ }
+ Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(selectedText.toString()), null);
} else if (jmi.equals(selectAllMenuItem)) {
- outputViewPane.selectAll();
+ resultsTable.selectAll();
}
}
};
copyMenuItem.addActionListener(actList);
- selectAllMenuItem.addActionListener(actList);
- Utilities.configureTextPaneAsHtml(outputViewPane);
+ selectAllMenuItem.addActionListener(actList);
}
/**
@@ -258,8 +315,9 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
private void resetComponents() {
currentPage = 1;
currentPageLabel.setText("");
+ artifactLabel.setText("");
totalPageLabel.setText("");
- outputViewPane.setText("");
+ ((DefaultTableModel) resultsTable.getModel()).setRowCount(0);
prevPageButton.setEnabled(false);
nextPageButton.setEnabled(false);
currentNode = null;
@@ -344,6 +402,101 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
}
}
+ /**
+ * This class is a container to hold the data necessary for each of the
+ * result pages associated with file or artifact beivng viewed.
+ */
+ private class ResultsTableArtifact {
+
+ private final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ private String[][] rowData = null;
+ private final String artifactDisplayName;
+
+ ResultsTableArtifact(BlackboardArtifact artifact) {
+ artifactDisplayName = artifact.getDisplayName();
+ addRows(artifact);
+
+ }
+
+ ResultsTableArtifact(String errorMsg) {
+ artifactDisplayName = errorMsg;
+ rowData = new String[1][3];
+ rowData[0] = new String[]{"", errorMsg, ""};
+
+ }
+
+ private String[][] getRows() {
+ return rowData;
+ }
+
+ private void addRows(BlackboardArtifact artifact) {
+ List rowsToAdd = new ArrayList<>();
+ try {
+ Content content = artifact.getSleuthkitCase().getContentById(artifact.getObjectID());
+ /*
+ * Add rows for each attribute.
+ */
+ for (BlackboardAttribute attr : artifact.getAttributes()) {
+ /*
+ * Attribute value column.
+ */
+ String value = "";
+ switch (attr.getAttributeType().getValueType()) {
+ case STRING:
+ case INTEGER:
+ case LONG:
+ case DOUBLE:
+ case BYTE:
+ default:
+ value = attr.getDisplayString();
+ break;
+ // Use Autopsy date formatting settings, not TSK defaults
+ case DATETIME:
+ long epoch = attr.getValueLong();
+ value = "0000-00-00 00:00:00";
+ if (null != content && 0 != epoch) {
+ dateFormatter.setTimeZone(ContentUtils.getTimeZone(content));
+ value = dateFormatter.format(new java.util.Date(epoch * 1000));
+ }
+ break;
+ }
+ /*
+ * Attribute sources column.
+ */
+ String sources = StringUtils.join(attr.getSources(), ", ");
+ rowsToAdd.add(new String[]{attr.getAttributeType().getDisplayName(), value, sources});
+ }
+ /*
+ * Add a row for the source content path.
+ */
+ String path = "";
+ try {
+ if (null != content) {
+ path = content.getUniquePath();
+ }
+ } catch (TskCoreException ex) {
+ logger.log(Level.SEVERE, String.format("Error getting source content path for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex);
+ path = Bundle.DataContentViewerArtifact_failedToGetSourcePath_message();
+ }
+ rowsToAdd.add(new String[]{"Source File Path", path, ""});
+ /*
+ * Add a row for the artifact id.
+ */
+ rowsToAdd.add(new String[]{"Artifact ID", Long.toString(artifact.getArtifactID()), ""});
+ } catch (TskCoreException ex) {
+ rowsToAdd.add(new String[]{"", Bundle.DataContentViewerArtifact_failedToGetAttributes_message(), ""});
+ }
+ rowData = rowsToAdd.toArray(new String[0][0]);
+ }
+
+ /**
+ * @return the artifactDisplayName
+ */
+ String getArtifactDisplayName() {
+ return artifactDisplayName;
+ }
+ }
+
/**
* Instances of this class are simple containers for view update information
* generated by a background thread.
@@ -352,12 +505,18 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
int numberOfPages;
int currentPage;
- String text;
+ ResultsTableArtifact tableContents;
- ViewUpdate(int numberOfPages, int currentPage, String text) {
+ ViewUpdate(int numberOfPages, int currentPage, ResultsTableArtifact contents) {
this.currentPage = currentPage;
this.numberOfPages = numberOfPages;
- this.text = text;
+ this.tableContents = contents;
+ }
+
+ ViewUpdate(int numberOfPages, int currentPage, String errorMsg) {
+ this.currentPage = currentPage;
+ this.numberOfPages = numberOfPages;
+ this.tableContents = new ResultsTableArtifact(errorMsg);
}
}
@@ -376,13 +535,15 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
currentPage = viewUpdate.currentPage;
totalPageLabel.setText(Integer.toString(viewUpdate.numberOfPages));
currentPageLabel.setText(Integer.toString(currentPage));
-
+ artifactLabel.setText(viewUpdate.tableContents.getArtifactDisplayName());
// @@@ This can take a long time. Perhaps a faster HTML renderer can be found.
// Note that the rendering appears to be done on a background thread, since the
// wait cursor reset below happens before the new text hits the JTextPane. On the
// other hand, the UI is unresponsive...
- outputViewPane.setText(viewUpdate.text);
- outputViewPane.moveCaretPosition(0);
+ DefaultTableModel tModel = ((DefaultTableModel) resultsTable.getModel());
+ tModel.setDataVector(viewUpdate.tableContents.getRows(), COLUMN_HEADERS);
+ updateColumnSizes();
+ resultsTable.clearSelection();
this.setCursor(null);
}
@@ -394,9 +555,12 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
* @param task A new SwingWorker object to execute as a background thread.
*/
private synchronized void startNewTask(SwingWorker task) {
- outputViewPane.setText(WAIT_TEXT);
- outputViewPane.moveCaretPosition(0);
-
+ String[][] waitRow = new String[1][3];
+ waitRow[0] = new String[]{"", WAIT_TEXT, ""};
+ DefaultTableModel tModel = ((DefaultTableModel) resultsTable.getModel());
+ tModel.setDataVector(waitRow, COLUMN_HEADERS);
+ updateColumnSizes();
+ resultsTable.clearSelection();
// The output of the previous task is no longer relevant.
if (currentTask != null) {
// This call sets a cancellation flag. It does not terminate the background thread running the task.
@@ -410,24 +574,25 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
}
/**
- * Populate the cache of artifact represented as strings.
+ * Populate the cache of artifact represented as ResultsTableArtifacts.
*
- * @param artifactStrings A list of string representations of artifacts.
+ * @param artifactList A list of ResultsTableArtifact representations of
+ * artifacts.
*/
- private void setArtifactContentStrings(List artifactStrings) {
+ private void setArtifactContents(List artifactList) {
synchronized (lock) {
- this.artifactContentStrings = artifactStrings;
+ this.artifactTableContents = artifactList;
}
}
/**
- * Retrieve the cache of artifact represented as strings.
+ * Retrieve the cache of artifact represented as ResultsTableArtifacts.
*
- * @return A list of string representations of artifacts.
+ * @return A list of ResultsTableArtifact representations of artifacts.
*/
- private List getArtifactContentStrings() {
+ private List getArtifactContents() {
synchronized (lock) {
- return artifactContentStrings;
+ return artifactTableContents;
}
}
@@ -453,7 +618,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
// Get the content.
Content content = lookup.lookup(Content.class);
if (content == null) {
- return new ViewUpdate(getArtifactContentStrings().size(), currentPage, ERROR_TEXT);
+ return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT);
}
// Get all of the blackboard artifacts associated with the content. These are what this
@@ -463,17 +628,17 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
artifacts = content.getAllArtifacts();
} catch (TskException ex) {
logger.log(Level.WARNING, "Couldn't get artifacts", ex); //NON-NLS
- return new ViewUpdate(getArtifactContentStrings().size(), currentPage, ERROR_TEXT);
+ return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT);
}
if (isCancelled()) {
return null;
}
- // Build the new artifact strings cache.
- ArrayList artifactStrings = new ArrayList<>();
+ // Build the new artifact contents cache.
+ ArrayList artifactContents = new ArrayList<>();
for (BlackboardArtifact artifact : artifacts) {
- artifactStrings.add(new ArtifactStringContent(artifact));
+ artifactContents.add(new ResultsTableArtifact(artifact));
}
// If the node has an underlying blackboard artifact, show it. If not,
@@ -514,19 +679,16 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
return null;
}
- // Add one to the index of the artifact string for the corresponding page index. Note that the getString() method
- // of ArtifactStringContent does a lazy fetch of the attributes of the correspoding artifact and represents them as
- // HTML.
- ViewUpdate viewUpdate = new ViewUpdate(artifactStrings.size(), index + 1, artifactStrings.get(index).getString());
+ // Add one to the index of the artifact content for the corresponding page index.
+ ViewUpdate viewUpdate = new ViewUpdate(artifactContents.size(), index + 1, artifactContents.get(index));
- // It may take a considerable amount of time to fetch the attributes of the selected artifact and render them
- // as HTML, so check for cancellation.
+ // It may take a considerable amount of time to fetch the attributes of the selected artifact
if (isCancelled()) {
return null;
}
- // Update the artifact strings cache.
- setArtifactContentStrings(artifactStrings);
+ // Update the artifact contents cache.
+ setArtifactContents(artifactContents);
return viewUpdate;
}
@@ -561,14 +723,10 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
@Override
protected ViewUpdate doInBackground() {
- // Get the artifact string to display from the cache. Note that one must be subtracted from the
- // page index to get the corresponding artifact string index.
- List artifactStrings = getArtifactContentStrings();
- ArtifactStringContent artifactStringContent = artifactStrings.get(pageIndex - 1);
-
- // The getString() method of ArtifactStringContent does a lazy fetch of the attributes of the
- // correspoding artifact and represents them as HTML.
- String artifactString = artifactStringContent.getString();
+ // Get the artifact content to display from the cache. Note that one must be subtracted from the
+ // page index to get the corresponding artifact content index.
+ List artifactContents = getArtifactContents();
+ ResultsTableArtifact artifactContent = artifactContents.get(pageIndex - 1);
// It may take a considerable amount of time to fetch the attributes of the selected artifact and render them
// as HTML, so check for cancellation.
@@ -576,7 +734,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
return null;
}
- return new ViewUpdate(artifactStrings.size(), pageIndex, artifactString);
+ return new ViewUpdate(artifactContents.size(), pageIndex, artifactContent);
}
@Override
diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ArtifactStringContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/ArtifactStringContent.java
index cece255c93..774d1f2f9e 100644
--- a/Core/src/org/sleuthkit/autopsy/datamodel/ArtifactStringContent.java
+++ b/Core/src/org/sleuthkit/autopsy/datamodel/ArtifactStringContent.java
@@ -19,7 +19,6 @@
package org.sleuthkit.autopsy.datamodel;
import java.text.SimpleDateFormat;
-import java.util.Arrays;
import java.util.logging.Level;
import org.apache.commons.lang.StringUtils;
import org.openide.util.NbBundle;
@@ -35,7 +34,10 @@ import org.sleuthkit.datamodel.TskCoreException;
* HTML, so any styling needs to be supplied by the display mechansim. For
* example, GUI components such as content viewers might use HTMLEditorKit to
* add styling.
+ *
+ * @deprecated - No longer used by DataContentViewerArtifact because the table is no longer HTML
*/
+@Deprecated
public class ArtifactStringContent implements StringContent {
private final static SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");