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);
 
  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;
 
  316             this.content = content;
 
  321             artifactDisplayName = errorMsg;
 
  322             rowData = 
new String[1][3];
 
  323             rowData[0] = 
new String[]{
"", errorMsg, 
""};
 
  332             List<String[]> rowsToAdd = 
new ArrayList<>();
 
  342                     switch (attr.getAttributeType().getValueType()) {
 
  350                             String jsonVal = attr.getValueString();
 
  351                             JsonElement jsonEl = JsonParser.parseString(jsonVal);
 
  352                             value = toJsonDisplayString(jsonEl, 
"");
 
  361                             value = attr.getDisplayString();
 
  367                     String sources = StringUtils.join(attr.getSources(), 
", ");
 
  368                     rowsToAdd.add(
new String[]{attr.getAttributeType().getDisplayName(), value, sources});
 
  375                     if (null != content) {
 
  379                     logger.log(Level.SEVERE, String.format(
"Error getting source content path for artifact (artifact_id=%d, obj_id=%d)", artifact.
getArtifactID(), artifact.
getObjectID()), ex);
 
  380                     path = Bundle.DataContentViewerArtifact_failedToGetSourcePath_message();
 
  382                 rowsToAdd.add(
new String[]{
"Source File Path", path, 
""});
 
  386                 rowsToAdd.add(
new String[]{
"Artifact ID", Long.toString(artifact.
getArtifactID()), 
""});
 
  388                 rowsToAdd.add(
new String[]{
"", Bundle.DataContentViewerArtifact_failedToGetAttributes_message(), 
""});
 
  390             rowData = rowsToAdd.toArray(
new String[0][0]);
 
  396         String getArtifactDisplayName() {
 
  397             return artifactDisplayName;
 
  400         private static final String INDENT_RIGHT = 
"    ";
 
  401         private static final String NEW_LINE = 
"\n";
 
  413             if (element == null || element.isJsonNull()) {
 
  415             } 
else if (element.isJsonPrimitive()) {
 
  416                 return element.getAsString();
 
  417             } 
else if (element.isJsonObject()) {
 
  418                 StringBuilder sb = 
new StringBuilder(
"");
 
  419                 JsonObject obj = element.getAsJsonObject();
 
  421                 for (Map.Entry<String, JsonElement> entry : obj.entrySet()) {
 
  422                     appendJsonElementToString(entry.getKey(), entry.getValue(), startIndent, sb);
 
  425                 String returnString = sb.toString();
 
  426                 if (startIndent.length() == 0 && returnString.startsWith(NEW_LINE)) {
 
  427                     returnString = returnString.substring(NEW_LINE.length());
 
  430             } 
else if (element.isJsonArray()) {
 
  431                 StringBuilder sb = 
new StringBuilder(
"");
 
  432                 JsonArray jsonArray = element.getAsJsonArray();
 
  433                 if (jsonArray.size() > 0) {
 
  435                     for (JsonElement arrayMember : jsonArray) {
 
  436                         sb.append(NEW_LINE).append(String.format(
"%s%d", startIndent, count));
 
  437                         sb.append(toJsonDisplayString(arrayMember, startIndent.concat(INDENT_RIGHT)));
 
  442                 String returnString = sb.toString();
 
  443                 if (startIndent.length() == 0 && returnString.startsWith(NEW_LINE)) {
 
  444                     returnString = returnString.substring(NEW_LINE.length());
 
  462             if (jsonElement.isJsonArray()) {
 
  463                 JsonArray jsonArray = jsonElement.getAsJsonArray();
 
  464                 if (jsonArray.size() > 0) {
 
  466                     sb.append(NEW_LINE).append(String.format(
"%s%s", startIndent, jsonKey));
 
  467                     for (JsonElement arrayMember : jsonArray) {
 
  468                         sb.append(NEW_LINE).append(String.format(
"%s%d", startIndent.concat(INDENT_RIGHT), count));
 
  469                         sb.append(toJsonDisplayString(arrayMember, startIndent.concat(INDENT_RIGHT).concat(INDENT_RIGHT)));
 
  473             } 
else if (jsonElement.isJsonObject()) {
 
  474                 sb.append(NEW_LINE).append(String.format(
"%s%s %s", startIndent, jsonKey, toJsonDisplayString(jsonElement.getAsJsonObject(), startIndent + INDENT_RIGHT)));
 
  475             } 
else if (jsonElement.isJsonPrimitive()) {
 
  476                 String attributeName = jsonKey;
 
  477                 String attributeValue;
 
  478                 if (attributeName.toUpperCase().contains(
"DATETIME")) {
 
  481                     attributeValue = jsonElement.getAsString();
 
  483                 sb.append(NEW_LINE).append(String.format(
"%s%s = %s", startIndent, attributeName, attributeValue));
 
  484             } 
else if (jsonElement.isJsonNull()) {
 
  485                 sb.append(NEW_LINE).append(String.format(
"%s%s = null", startIndent, jsonKey));
 
  498         this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
 
  499         DefaultTableModel tModel = ((DefaultTableModel) resultsTable.getModel());
 
  500         String[][] rows = resultsTableArtifact == null ? 
new String[0][0] : resultsTableArtifact.
getRows();
 
  501         tModel.setDataVector(rows, COLUMN_HEADERS);
 
  504         resultsTable.clearSelection();
 
  505         this.setCursor(null);
 
  515             javax.swing.JTextArea jtex = 
new javax.swing.JTextArea();
 
  516             if (value instanceof String) {
 
  517                 jtex.setText((String) value);
 
  518                 jtex.setLineWrap(
true);
 
  519                 jtex.setWrapStyleWord(
false);
 
  523                 jtex.setBackground(javax.swing.UIManager.getColor(
"Table.selectionBackground"));
 
  525                 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
 
List< BlackboardAttribute > getAttributes()
 
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()