19 package org.sleuthkit.autopsy.contentviewers.artifactviewers;
 
   21 import java.awt.Component;
 
   22 import java.awt.Cursor;
 
   23 import java.awt.Toolkit;
 
   24 import java.awt.event.ActionEvent;
 
   25 import java.awt.event.ActionListener;
 
   26 import java.awt.datatransfer.StringSelection;
 
   27 import java.text.SimpleDateFormat;
 
   28 import java.util.ArrayList;
 
   29 import java.util.Enumeration;
 
   30 import java.util.List;
 
   31 import java.util.logging.Level;
 
   32 import javax.swing.JMenuItem;
 
   33 import javax.swing.JTextArea;
 
   34 import javax.swing.event.ChangeEvent;
 
   35 import javax.swing.event.ListSelectionEvent;
 
   36 import javax.swing.event.TableColumnModelEvent;
 
   37 import javax.swing.table.DefaultTableModel;
 
   38 import javax.swing.table.TableColumn;
 
   39 import javax.swing.event.TableColumnModelListener;
 
   40 import javax.swing.text.View;
 
   41 import org.apache.commons.lang.StringUtils;
 
   42 import org.openide.util.NbBundle;
 
   48 import org.netbeans.swing.etable.ETable;
 
   49 import com.google.gson.JsonElement;
 
   50 import com.google.gson.JsonObject;
 
   51 import com.google.gson.JsonParser;
 
   52 import com.google.gson.JsonArray;
 
   53 import java.util.Locale;
 
   55 import javax.swing.SwingUtilities;
 
   63 @SuppressWarnings(
"PMD.SingularField") 
 
   67         "DefaultTableArtifactContentViewer.attrsTableHeader.type=Type",
 
   68         "DefaultTableArtifactContentViewer.attrsTableHeader.value=Value",
 
   69         "DefaultTableArtifactContentViewer.attrsTableHeader.sources=Source(s)",
 
   70         "DataContentViewerArtifact.failedToGetSourcePath.message=Failed to get source file path from case database",
 
   71         "DataContentViewerArtifact.failedToGetAttributes.message=Failed to get some or all attributes from case database" 
   76     private static final long serialVersionUID = 1L;
 
   78     private static final String[] COLUMN_HEADERS = {
 
   79         Bundle.DefaultTableArtifactContentViewer_attrsTableHeader_type(),
 
   80         Bundle.DefaultTableArtifactContentViewer_attrsTableHeader_value(),
 
   81         Bundle.DefaultTableArtifactContentViewer_attrsTableHeader_sources()};
 
   82     private static final int[] COLUMN_WIDTHS = {100, 800, 100};
 
   83     private static final int CELL_BOTTOM_MARGIN = 5;
 
   84     private static final int CELL_RIGHT_MARGIN = 1;
 
   89         resultsTableScrollPane.setViewportView(resultsTable);
 
   90         customizeComponents();
 
   96         resultsTable = 
new ETable();
 
   97         resultsTable.setModel(
new javax.swing.table.DefaultTableModel() {
 
   98             private static final long serialVersionUID = 1L;
 
  101             public boolean isCellEditable(
int rowIndex, 
int columnIndex) {
 
  105         resultsTable.setCellSelectionEnabled(
true);
 
  106         resultsTable.getTableHeader().setReorderingAllowed(
false);
 
  107         resultsTable.setColumnHidingAllowed(
false);
 
  108         resultsTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION);
 
  109         resultsTable.getColumnModel().addColumnModelListener(
new TableColumnModelListener() {
 
  112             public void columnAdded(TableColumnModelEvent e) {
 
  117             public void columnRemoved(TableColumnModelEvent e) {
 
  122             public void columnMoved(TableColumnModelEvent e) {
 
  127             public void columnMarginChanged(ChangeEvent e) {
 
  132             public void columnSelectionChanged(ListSelectionEvent e) {
 
  136         resultsTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_NEXT_COLUMN);
 
  144         int valueColIndex = -1;
 
  145         for (
int col = 0; col < resultsTable.getColumnCount(); col++) {
 
  146             if (resultsTable.getColumnName(col).equals(COLUMN_HEADERS[1])) {
 
  150         if (valueColIndex != -1) {
 
  151             for (
int row = 0; row < resultsTable.getRowCount(); row++) {
 
  152                 Component comp = resultsTable.prepareRenderer(
 
  153                         resultsTable.getCellRenderer(row, valueColIndex), row, valueColIndex);
 
  155                 if (comp instanceof JTextArea) {
 
  156                     final JTextArea tc = (JTextArea) comp;
 
  157                     final View rootView = tc.getUI().getRootView(tc);
 
  158                     java.awt.Insets i = tc.getInsets();
 
  159                     rootView.setSize(resultsTable.getColumnModel().getColumn(valueColIndex)
 
  160                             .getWidth() - (i.left + i.right + CELL_RIGHT_MARGIN), 
 
  162                     rowHeight = (int) rootView.getPreferredSpan(View.Y_AXIS);
 
  164                     rowHeight = comp.getPreferredSize().height;
 
  167                     resultsTable.setRowHeight(row, rowHeight + CELL_BOTTOM_MARGIN);
 
  177         Enumeration<TableColumn> columns = resultsTable.getColumnModel().getColumns();
 
  178         while (columns.hasMoreElements()) {
 
  179             TableColumn col = columns.nextElement();
 
  180             if (col.getHeaderValue().equals(COLUMN_HEADERS[0])) {
 
  181                 col.setPreferredWidth(COLUMN_WIDTHS[0]);
 
  182             } 
else if (col.getHeaderValue().equals(COLUMN_HEADERS[1])) {
 
  183                 col.setPreferredWidth(COLUMN_WIDTHS[1]);
 
  184             } 
else if (col.getHeaderValue().equals(COLUMN_HEADERS[2])) {
 
  185                 col.setPreferredWidth(COLUMN_WIDTHS[2]);
 
  195     @SuppressWarnings(
"unchecked")
 
  197     private 
void initComponents() {
 
  199         rightClickMenu = 
new javax.swing.JPopupMenu();
 
  200         copyMenuItem = 
new javax.swing.JMenuItem();
 
  201         selectAllMenuItem = 
new javax.swing.JMenuItem();
 
  202         resultsTableScrollPane = 
new javax.swing.JScrollPane();
 
  205         rightClickMenu.add(copyMenuItem);
 
  208         rightClickMenu.add(selectAllMenuItem);
 
  210         setPreferredSize(
new java.awt.Dimension(0, 0));
 
  212         resultsTableScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
 
  213         resultsTableScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
 
  214         resultsTableScrollPane.setMinimumSize(
new java.awt.Dimension(0, 0));
 
  215         resultsTableScrollPane.setPreferredSize(
new java.awt.Dimension(0, 0));
 
  217         javax.swing.GroupLayout layout = 
new javax.swing.GroupLayout(
this);
 
  218         this.setLayout(layout);
 
  219         layout.setHorizontalGroup(
 
  220             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  221             .addComponent(resultsTableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 100, Short.MAX_VALUE)
 
  223         layout.setVerticalGroup(
 
  224             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  225             .addComponent(resultsTableScrollPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 58, Short.MAX_VALUE)
 
  238         resultsTable.setComponentPopupMenu(rightClickMenu);
 
  239         ActionListener actList = 
new ActionListener() {
 
  241             public void actionPerformed(ActionEvent e) {
 
  242                 JMenuItem jmi = (JMenuItem) e.getSource();
 
  243                 if (jmi.equals(copyMenuItem)) {
 
  244                     StringBuilder selectedText = 
new StringBuilder(512);
 
  245                     for (
int row : resultsTable.getSelectedRows()) {
 
  246                         for (
int col : resultsTable.getSelectedColumns()) {
 
  247                             selectedText.append((String) resultsTable.getValueAt(row, col));
 
  248                             selectedText.append(
'\t');
 
  251                         if (row != resultsTable.getSelectedRows()[resultsTable.getSelectedRows().length - 1]) {
 
  252                             selectedText.append(System.lineSeparator());
 
  255                     Toolkit.getDefaultToolkit().getSystemClipboard().setContents(
new StringSelection(selectedText.toString()), null);
 
  256                 } 
else if (jmi.equals(selectAllMenuItem)) {
 
  257                     resultsTable.selectAll();
 
  261         copyMenuItem.addActionListener(actList);
 
  263         selectAllMenuItem.addActionListener(actList);
 
  271         ((DefaultTableModel) resultsTable.getModel()).setRowCount(0);
 
  284             SwingUtilities.invokeLater(
new Runnable() {
 
  287                     updateView(resultsTableArtifact);
 
  291         } 
catch (TskCoreException ex) {
 
  292             logger.log(Level.SEVERE, String.format(
"Error getting parent content for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex);
 
  309         private final SimpleDateFormat dateFormatter = 
new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.US);
 
  310         private String[][] rowData = null;
 
  315             artifactDisplayName = artifact.getDisplayName();
 
  316             this.content = content;
 
  321             artifactDisplayName = errorMsg;
 
  322             rowData = 
new String[1][3];
 
  323             rowData[0] = 
new String[]{
"", errorMsg, 
""};
 
  331         private void addRows(BlackboardArtifact artifact) {
 
  332             List<String[]> rowsToAdd = 
new ArrayList<>();
 
  337                 for (BlackboardAttribute attr : artifact.getAttributes()) {
 
  342                     switch (attr.getAttributeType().getValueType()) {
 
  350                             String jsonVal = attr.getValueString();
 
  351                             JsonParser parser = 
new JsonParser();
 
  352                             JsonObject json = parser.parse(jsonVal).getAsJsonObject();
 
  354                             value = toJsonDisplayString(json, 
"");
 
  363                             value = attr.getDisplayString();
 
  369                     String sources = StringUtils.join(attr.getSources(), 
", ");
 
  370                     rowsToAdd.add(
new String[]{attr.getAttributeType().getDisplayName(), value, sources});
 
  377                     if (null != content) {
 
  378                         path = content.getUniquePath();
 
  380                 } 
catch (TskCoreException ex) {
 
  381                     logger.log(Level.SEVERE, String.format(
"Error getting source content path for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex);
 
  382                     path = Bundle.DataContentViewerArtifact_failedToGetSourcePath_message();
 
  384                 rowsToAdd.add(
new String[]{
"Source File Path", path, 
""});
 
  388                 rowsToAdd.add(
new String[]{
"Artifact ID", Long.toString(artifact.getArtifactID()), 
""});
 
  389             } 
catch (TskCoreException ex) {
 
  390                 rowsToAdd.add(
new String[]{
"", Bundle.DataContentViewerArtifact_failedToGetAttributes_message(), 
""});
 
  392             rowData = rowsToAdd.toArray(
new String[0][0]);
 
  398         String getArtifactDisplayName() {
 
  399             return artifactDisplayName;
 
  402         private static final String INDENT_RIGHT = 
"    ";
 
  403         private static final String NEW_LINE = 
"\n";
 
  416             StringBuilder sb = 
new StringBuilder(
"");
 
  417             JsonObject obj = element.getAsJsonObject();
 
  419             for (Map.Entry<String, JsonElement> entry : obj.entrySet()) {
 
  420                 appendJsonElementToString(entry.getKey(), entry.getValue(), startIndent, sb);
 
  423             String returnString = sb.toString();
 
  424             if (startIndent.length() == 0 && returnString.startsWith(NEW_LINE)) {
 
  425                 returnString = returnString.substring(NEW_LINE.length());
 
  440             if (jsonElement.isJsonArray()) {
 
  441                 JsonArray jsonArray = jsonElement.getAsJsonArray();
 
  442                 if (jsonArray.size() > 0) {
 
  444                     sb.append(NEW_LINE).append(String.format(
"%s%s", startIndent, jsonKey));
 
  445                     for (JsonElement arrayMember : jsonArray) {
 
  446                         sb.append(NEW_LINE).append(String.format(
"%s%d", startIndent.concat(INDENT_RIGHT), count));
 
  447                         sb.append(toJsonDisplayString(arrayMember, startIndent.concat(INDENT_RIGHT).concat(INDENT_RIGHT)));
 
  451             } 
else if (jsonElement.isJsonObject()) {
 
  452                 sb.append(NEW_LINE).append(String.format(
"%s%s %s", startIndent, jsonKey, toJsonDisplayString(jsonElement.getAsJsonObject(), startIndent + INDENT_RIGHT)));
 
  453             } 
else if (jsonElement.isJsonPrimitive()) {
 
  454                 String attributeName = jsonKey;
 
  455                 String attributeValue;
 
  456                 if (attributeName.toUpperCase().contains(
"DATETIME")) {
 
  459                     attributeValue = jsonElement.getAsString();
 
  461                 sb.append(NEW_LINE).append(String.format(
"%s%s = %s", startIndent, attributeName, attributeValue));
 
  462             } 
else if (jsonElement.isJsonNull()) {
 
  463                 sb.append(NEW_LINE).append(String.format(
"%s%s = null", startIndent, jsonKey));
 
  476         this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
 
  477         DefaultTableModel tModel = ((DefaultTableModel) resultsTable.getModel());
 
  478         String[][] rows = resultsTableArtifact == null ? 
new String[0][0] : resultsTableArtifact.
getRows();
 
  479         tModel.setDataVector(rows, COLUMN_HEADERS);
 
  482         resultsTable.clearSelection();
 
  483         this.setCursor(null);
 
  493             javax.swing.JTextArea jtex = 
new javax.swing.JTextArea();
 
  494             if (value instanceof String) {
 
  495                 jtex.setText((String) value);
 
  496                 jtex.setLineWrap(
true);
 
  497                 jtex.setWrapStyleWord(
false);
 
  501                 jtex.setBackground(javax.swing.UIManager.getColor(
"Table.selectionBackground"));
 
  503                 jtex.setBackground(javax.swing.UIManager.getColor(
"Table.background"));
 
final String artifactDisplayName
 
javax.swing.JMenuItem copyMenuItem
 
void customizeComponents()
 
static String getFormattedTime(long epochTime)
 
void updateView(ResultsTableArtifact resultsTableArtifact)
 
String toJsonDisplayString(JsonElement element, String startIndent)
 
Component getTableCellRendererComponent(javax.swing.JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
 
boolean isSupported(BlackboardArtifact artifact)
 
javax.swing.JPopupMenu rightClickMenu
 
javax.swing.JMenuItem selectAllMenuItem
 
synchronized static Logger getLogger(String name)
 
void appendJsonElementToString(String jsonKey, JsonElement jsonElement, String startIndent, StringBuilder sb)
 
javax.swing.JScrollPane resultsTableScrollPane
 
void setArtifact(BlackboardArtifact artifact)
 
void addRows(BlackboardArtifact artifact)
 
DefaultTableArtifactContentViewer()