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()