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 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) {
376 path = content.getUniquePath();
378 }
catch (TskCoreException ex) {
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()),
""});
387 }
catch (TskCoreException ex) {
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
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()