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 JsonObject json = JsonParser.parseString(jsonVal).getAsJsonObject();
353 value = toJsonDisplayString(json,
"");
362 value = attr.getDisplayString();
368 String sources = StringUtils.join(attr.getSources(),
", ");
369 rowsToAdd.add(
new String[]{attr.getAttributeType().getDisplayName(), value, sources});
376 if (null != content) {
377 path = content.getUniquePath();
379 }
catch (TskCoreException ex) {
380 logger.log(Level.SEVERE, String.format(
"Error getting source content path for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex);
381 path = Bundle.DataContentViewerArtifact_failedToGetSourcePath_message();
383 rowsToAdd.add(
new String[]{
"Source File Path", path,
""});
387 rowsToAdd.add(
new String[]{
"Artifact ID", Long.toString(artifact.getArtifactID()),
""});
388 }
catch (TskCoreException ex) {
389 rowsToAdd.add(
new String[]{
"", Bundle.DataContentViewerArtifact_failedToGetAttributes_message(),
""});
391 rowData = rowsToAdd.toArray(
new String[0][0]);
397 String getArtifactDisplayName() {
398 return artifactDisplayName;
401 private static final String INDENT_RIGHT =
" ";
402 private static final String NEW_LINE =
"\n";
415 StringBuilder sb =
new StringBuilder(
"");
416 JsonObject obj = element.getAsJsonObject();
418 for (Map.Entry<String, JsonElement> entry : obj.entrySet()) {
419 appendJsonElementToString(entry.getKey(), entry.getValue(), startIndent, sb);
422 String returnString = sb.toString();
423 if (startIndent.length() == 0 && returnString.startsWith(NEW_LINE)) {
424 returnString = returnString.substring(NEW_LINE.length());
439 if (jsonElement.isJsonArray()) {
440 JsonArray jsonArray = jsonElement.getAsJsonArray();
441 if (jsonArray.size() > 0) {
443 sb.append(NEW_LINE).append(String.format(
"%s%s", startIndent, jsonKey));
444 for (JsonElement arrayMember : jsonArray) {
445 sb.append(NEW_LINE).append(String.format(
"%s%d", startIndent.concat(INDENT_RIGHT), count));
446 sb.append(toJsonDisplayString(arrayMember, startIndent.concat(INDENT_RIGHT).concat(INDENT_RIGHT)));
450 }
else if (jsonElement.isJsonObject()) {
451 sb.append(NEW_LINE).append(String.format(
"%s%s %s", startIndent, jsonKey, toJsonDisplayString(jsonElement.getAsJsonObject(), startIndent + INDENT_RIGHT)));
452 }
else if (jsonElement.isJsonPrimitive()) {
453 String attributeName = jsonKey;
454 String attributeValue;
455 if (attributeName.toUpperCase().contains(
"DATETIME")) {
458 attributeValue = jsonElement.getAsString();
460 sb.append(NEW_LINE).append(String.format(
"%s%s = %s", startIndent, attributeName, attributeValue));
461 }
else if (jsonElement.isJsonNull()) {
462 sb.append(NEW_LINE).append(String.format(
"%s%s = null", startIndent, jsonKey));
475 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
476 DefaultTableModel tModel = ((DefaultTableModel) resultsTable.getModel());
477 String[][] rows = resultsTableArtifact == null ?
new String[0][0] : resultsTableArtifact.
getRows();
478 tModel.setDataVector(rows, COLUMN_HEADERS);
481 resultsTable.clearSelection();
482 this.setCursor(null);
492 javax.swing.JTextArea jtex =
new javax.swing.JTextArea();
493 if (value instanceof String) {
494 jtex.setText((String) value);
495 jtex.setLineWrap(
true);
496 jtex.setWrapStyleWord(
false);
500 jtex.setBackground(javax.swing.UIManager.getColor(
"Table.selectionBackground"));
502 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()