mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-14 17:06:16 +00:00
Merge pull request #3383 from raman-bt/sqliteviewer
3415: SQLite Viewer - Show Table Content
This commit is contained in:
commit
45348063a8
@ -35,5 +35,11 @@ MessageContentViewer.attachmentsPanel.TabConstraints.tabTitle=Attachments
|
|||||||
MessageContentViewer.viewInNewWindowButton.text=View in New Window
|
MessageContentViewer.viewInNewWindowButton.text=View in New Window
|
||||||
JPEGViewerDummy.jLabel1.text=You are looking at a JPEG file:
|
JPEGViewerDummy.jLabel1.text=You are looking at a JPEG file:
|
||||||
JPEGViewerDummy.jTextField1.text=jTextField1
|
JPEGViewerDummy.jTextField1.text=jTextField1
|
||||||
SQLiteViewer.jLabel1.text=Table
|
SQLiteViewer.nextPageButton.text=
|
||||||
|
SQLiteViewer.prevPageButton.text=
|
||||||
|
SQLiteViewer.numPagesLabel.text=N
|
||||||
|
SQLiteViewer.jLabel3.text=of
|
||||||
|
SQLiteViewer.currPageLabel.text=x
|
||||||
|
SQLiteViewer.jLabel2.text=Page
|
||||||
SQLiteViewer.numEntriesField.text=num Entries
|
SQLiteViewer.numEntriesField.text=num Entries
|
||||||
|
SQLiteViewer.jLabel1.text=Table
|
||||||
|
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2018 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.contentviewers;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import org.openide.nodes.AbstractNode;
|
||||||
|
import org.openide.nodes.ChildFactory;
|
||||||
|
import org.openide.nodes.Children;
|
||||||
|
import org.openide.nodes.Node;
|
||||||
|
import org.openide.nodes.Sheet;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
||||||
|
|
||||||
|
public class SQLiteTableRowFactory extends ChildFactory<Integer> {
|
||||||
|
|
||||||
|
private final List<Map<String, Object>> rows;
|
||||||
|
|
||||||
|
public SQLiteTableRowFactory(List<Map<String, Object>> rows) {
|
||||||
|
this.rows = rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean createKeys(List<Integer> keys) {
|
||||||
|
if (rows != null) {
|
||||||
|
for (int i = 0; i < rows.size(); i++) {
|
||||||
|
keys.add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Node createNodeForKey(Integer key) {
|
||||||
|
if (Objects.isNull(rows) || rows.isEmpty() || key >= rows.size()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SQLiteTableRowNode(rows.get(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class SQLiteTableRowNode extends AbstractNode {
|
||||||
|
|
||||||
|
private final Map<String, Object> row;
|
||||||
|
|
||||||
|
SQLiteTableRowNode(Map<String, Object> row) {
|
||||||
|
super(Children.LEAF);
|
||||||
|
this.row = row;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Sheet createSheet() {
|
||||||
|
|
||||||
|
Sheet s = super.createSheet();
|
||||||
|
Sheet.Set properties = s.get(Sheet.PROPERTIES);
|
||||||
|
if (properties == null) {
|
||||||
|
properties = Sheet.createPropertiesSet();
|
||||||
|
s.put(properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map.Entry<String, Object> col : row.entrySet()) {
|
||||||
|
String colName = col.getKey();
|
||||||
|
String colVal = col.getValue().toString();
|
||||||
|
|
||||||
|
properties.put(new NodeProperty<>(colName, colName, colName, colVal)); // NON-NLS
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||||
|
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||||
|
</Form>
|
@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2018 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.contentviewers;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JTable;
|
||||||
|
import javax.swing.ListSelectionModel;
|
||||||
|
import javax.swing.ScrollPaneConstants;
|
||||||
|
import javax.swing.SwingWorker;
|
||||||
|
import javax.swing.table.TableCellRenderer;
|
||||||
|
import javax.swing.table.TableColumnModel;
|
||||||
|
import org.netbeans.swing.etable.ETableColumn;
|
||||||
|
import org.netbeans.swing.etable.ETableColumnModel;
|
||||||
|
import org.netbeans.swing.outline.Outline;
|
||||||
|
import org.openide.explorer.ExplorerManager;
|
||||||
|
import org.openide.nodes.AbstractNode;
|
||||||
|
import org.openide.nodes.Children;
|
||||||
|
|
||||||
|
class SQLiteTableView extends JPanel implements ExplorerManager.Provider {
|
||||||
|
|
||||||
|
private final org.openide.explorer.view.OutlineView outlineView;
|
||||||
|
private final Outline outline;
|
||||||
|
private final ExplorerManager explorerManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new form SQLiteTableView
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
SQLiteTableView() {
|
||||||
|
|
||||||
|
initComponents();
|
||||||
|
outlineView = new org.openide.explorer.view.OutlineView();
|
||||||
|
add(outlineView, BorderLayout.CENTER);
|
||||||
|
outlineView.setPropertyColumns(); // column headers will be set later
|
||||||
|
outlineView.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
|
||||||
|
outlineView.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
|
||||||
|
|
||||||
|
outline = outlineView.getOutline();
|
||||||
|
|
||||||
|
outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||||
|
outline.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
|
||||||
|
outline.setRowSelectionAllowed(false);
|
||||||
|
outline.setRootVisible(false);
|
||||||
|
|
||||||
|
explorerManager = new ExplorerManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up the columns in the display table
|
||||||
|
*
|
||||||
|
* @param tableRows
|
||||||
|
*/
|
||||||
|
void setupTable(List<Map<String, Object>> tableRows) {
|
||||||
|
|
||||||
|
|
||||||
|
if (Objects.isNull(tableRows) || tableRows.isEmpty()) {
|
||||||
|
outlineView.setPropertyColumns();
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Set up the column names
|
||||||
|
Map<String, Object> row = tableRows.get(0);
|
||||||
|
String[] propStrings = new String[row.size() * 2];
|
||||||
|
int i = 0;
|
||||||
|
for (Map.Entry<String, Object> col : row.entrySet()) {
|
||||||
|
String colName = col.getKey();
|
||||||
|
propStrings[2 * i] = colName;
|
||||||
|
propStrings[2 * i + 1] = colName;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
outlineView.setPropertyColumns(propStrings);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide the 'Nodes' column
|
||||||
|
TableColumnModel columnModel = outline.getColumnModel();
|
||||||
|
ETableColumn column = (ETableColumn) columnModel.getColumn(0);
|
||||||
|
((ETableColumnModel) columnModel).setColumnHidden(column, true);
|
||||||
|
|
||||||
|
// Set the Nodes for the ExplorerManager.
|
||||||
|
// The Swingworker ensures that setColumnWidths() is called after all nodes have been created.
|
||||||
|
new SwingWorker<Boolean, Void>() {
|
||||||
|
@Override
|
||||||
|
protected Boolean doInBackground() throws Exception {
|
||||||
|
|
||||||
|
explorerManager.setRootContext(new AbstractNode(Children.create(new SQLiteTableRowFactory(tableRows), true)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void done() {
|
||||||
|
super.done();
|
||||||
|
|
||||||
|
setColumnWidths();
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setColumnWidths() {
|
||||||
|
int margin = 4;
|
||||||
|
int padding = 8;
|
||||||
|
|
||||||
|
// find the maximum width needed to fit the values for the first N rows, at most
|
||||||
|
final int rows = Math.min(20, outline.getRowCount());
|
||||||
|
for (int col = 1; col < outline.getColumnCount(); col++) {
|
||||||
|
int columnWidthLimit = 500;
|
||||||
|
int columnWidth = 50;
|
||||||
|
|
||||||
|
for (int row = 0; row < rows; row++) {
|
||||||
|
TableCellRenderer renderer = outline.getCellRenderer(row, col);
|
||||||
|
Component comp = outline.prepareRenderer(renderer, row, col);
|
||||||
|
|
||||||
|
columnWidth = Math.max(comp.getPreferredSize().width, columnWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
columnWidth += 2 * margin + padding; // add margin and regular padding
|
||||||
|
columnWidth = Math.min(columnWidth, columnWidthLimit);
|
||||||
|
outline.getColumnModel().getColumn(col).setPreferredWidth(columnWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called from within the constructor to initialize the form.
|
||||||
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
|
* regenerated by the Form Editor.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
|
||||||
|
setLayout(new java.awt.BorderLayout());
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExplorerManager getExplorerManager() {
|
||||||
|
return explorerManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
<Form version="1.9" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
<AuxValues>
|
<AuxValues>
|
||||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
@ -16,22 +16,27 @@
|
|||||||
<Layout>
|
<Layout>
|
||||||
<DimensionLayout dim="0">
|
<DimensionLayout dim="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="jHdrPanel" alignment="0" max="32767" attributes="0"/>
|
<Component id="jHdrPanel" max="32767" attributes="0"/>
|
||||||
<Component id="jTableDataPanel" alignment="0" max="32767" attributes="0"/>
|
<Component id="jTableDataPanel" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<Component id="jHdrPanel" min="-2" max="-2" attributes="0"/>
|
<Component id="jHdrPanel" min="-2" pref="53" max="-2" attributes="0"/>
|
||||||
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
|
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
||||||
<Component id="jTableDataPanel" max="32767" attributes="0"/>
|
<Component id="jTableDataPanel" pref="317" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
</Layout>
|
</Layout>
|
||||||
<SubComponents>
|
<SubComponents>
|
||||||
<Container class="javax.swing.JPanel" name="jHdrPanel">
|
<Container class="javax.swing.JPanel" name="jHdrPanel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[536, 40]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
|
||||||
<Layout>
|
<Layout>
|
||||||
<DimensionLayout dim="0">
|
<DimensionLayout dim="0">
|
||||||
@ -39,11 +44,23 @@
|
|||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
|
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="tablesDropdownList" min="-2" pref="130" max="-2" attributes="0"/>
|
<Component id="tablesDropdownList" min="-2" pref="130" max="-2" attributes="0"/>
|
||||||
<EmptySpace min="-2" pref="23" max="-2" attributes="0"/>
|
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||||
<Component id="numEntriesField" min="-2" pref="71" max="-2" attributes="0"/>
|
<Component id="numEntriesField" min="-2" pref="71" max="-2" attributes="0"/>
|
||||||
<EmptySpace pref="130" max="32767" attributes="0"/>
|
<EmptySpace min="-2" pref="15" max="-2" attributes="0"/>
|
||||||
|
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="currPageLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="jLabel3" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="numPagesLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||||
|
<Component id="prevPageButton" min="-2" pref="23" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||||
|
<Component id="nextPageButton" min="-2" pref="23" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace pref="133" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
@ -51,12 +68,20 @@
|
|||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="3" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="tablesDropdownList" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="nextPageButton" alignment="0" min="-2" pref="23" max="-2" attributes="0"/>
|
||||||
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="prevPageButton" alignment="0" min="-2" pref="23" max="-2" attributes="0"/>
|
||||||
<Component id="numEntriesField" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Group type="103" groupAlignment="3" attributes="0">
|
||||||
|
<Component id="tablesDropdownList" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="numEntriesField" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="jLabel2" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="currPageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="jLabel3" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="numPagesLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace pref="16" max="32767" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
@ -97,57 +122,88 @@
|
|||||||
<Border info="null"/>
|
<Border info="null"/>
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="jLabel2">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="SQLiteViewer.jLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="currPageLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="SQLiteViewer.currPageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="jLabel3">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="SQLiteViewer.jLabel3.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="numPagesLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="SQLiteViewer.numPagesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JButton" name="prevPageButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||||
|
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_back.png"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="SQLiteViewer.prevPageButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="borderPainted" type="boolean" value="false"/>
|
||||||
|
<Property name="contentAreaFilled" type="boolean" value="false"/>
|
||||||
|
<Property name="disabledSelectedIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||||
|
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_back_disabled.png"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||||
|
<Insets value="[2, 0, 2, 0]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[23, 23]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
<Events>
|
<Events>
|
||||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="numEntriesFieldActionPerformed"/>
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="prevPageButtonActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JButton" name="nextPageButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||||
|
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="SQLiteViewer.nextPageButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="borderPainted" type="boolean" value="false"/>
|
||||||
|
<Property name="contentAreaFilled" type="boolean" value="false"/>
|
||||||
|
<Property name="disabledSelectedIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||||
|
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_forward_disabled.png"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||||
|
<Insets value="[2, 0, 2, 0]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[23, 23]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="nextPageButtonActionPerformed"/>
|
||||||
</Events>
|
</Events>
|
||||||
</Component>
|
</Component>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
<Container class="javax.swing.JPanel" name="jTableDataPanel">
|
<Container class="javax.swing.JPanel" name="jTableDataPanel">
|
||||||
|
|
||||||
<Layout>
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||||
<DimensionLayout dim="0">
|
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
|
||||||
<Group type="102" alignment="0" attributes="0">
|
|
||||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
|
||||||
<Component id="jScrollPane1" pref="0" max="32767" attributes="0"/>
|
|
||||||
<EmptySpace min="-2" pref="15" max="-2" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
|
||||||
</DimensionLayout>
|
|
||||||
<DimensionLayout dim="1">
|
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
|
||||||
<Group type="102" alignment="0" attributes="0">
|
|
||||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
|
||||||
<Component id="jScrollPane1" pref="275" max="32767" attributes="0"/>
|
|
||||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
|
||||||
</DimensionLayout>
|
|
||||||
</Layout>
|
|
||||||
<SubComponents>
|
|
||||||
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
|
|
||||||
<AuxValues>
|
|
||||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
|
||||||
</AuxValues>
|
|
||||||
|
|
||||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
|
||||||
<SubComponents>
|
|
||||||
<Component class="javax.swing.JTable" name="jTable1">
|
|
||||||
<Properties>
|
|
||||||
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
|
|
||||||
<Table columnCount="4" rowCount="4">
|
|
||||||
<Column editable="true" title="Title 1" type="java.lang.Object"/>
|
|
||||||
<Column editable="true" title="Title 2" type="java.lang.Object"/>
|
|
||||||
<Column editable="true" title="Title 3" type="java.lang.Object"/>
|
|
||||||
<Column editable="true" title="Title 4" type="java.lang.Object"/>
|
|
||||||
</Table>
|
|
||||||
</Property>
|
|
||||||
</Properties>
|
|
||||||
</Component>
|
|
||||||
</SubComponents>
|
|
||||||
</Container>
|
|
||||||
</SubComponents>
|
|
||||||
</Container>
|
</Container>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -18,22 +18,29 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.contentviewers;
|
package org.sleuthkit.autopsy.contentviewers;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.DriverManager;
|
import java.sql.DriverManager;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.Statement;
|
import java.sql.ResultSetMetaData;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.logging.Level;
|
||||||
import javax.swing.JComboBox;
|
import javax.swing.JComboBox;
|
||||||
import javax.swing.SwingWorker;
|
import javax.swing.SwingWorker;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||||
@ -48,16 +55,22 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
|
|||||||
private String tmpDBPathName = null;
|
private String tmpDBPathName = null;
|
||||||
private File tmpDBFile = null;
|
private File tmpDBFile = null;
|
||||||
|
|
||||||
// TBD: Change the value to be a Array of ColDefs
|
private final Map<String, String> dbTablesMap = new TreeMap<>();
|
||||||
Map<String, String> dbTablesMap = new TreeMap<>();
|
|
||||||
|
private static final int ROWS_PER_PAGE = 100;
|
||||||
|
private int numRows; // num of rows in the selected table
|
||||||
|
private int currPage = 0; // curr page of rows being displayed
|
||||||
|
|
||||||
|
SQLiteTableView selectedTableView = new SQLiteTableView();
|
||||||
|
|
||||||
|
private SwingWorker<? extends Object, ? extends Object> worker;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new form SQLiteViewer
|
* Creates new form SQLiteViewer
|
||||||
*/
|
*/
|
||||||
public SQLiteViewer() {
|
public SQLiteViewer() {
|
||||||
initComponents();
|
initComponents();
|
||||||
|
jTableDataPanel.add(selectedTableView, BorderLayout.CENTER);
|
||||||
customizeComponents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,9 +86,15 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
|
|||||||
tablesDropdownList = new javax.swing.JComboBox<>();
|
tablesDropdownList = new javax.swing.JComboBox<>();
|
||||||
jLabel1 = new javax.swing.JLabel();
|
jLabel1 = new javax.swing.JLabel();
|
||||||
numEntriesField = new javax.swing.JTextField();
|
numEntriesField = new javax.swing.JTextField();
|
||||||
|
jLabel2 = new javax.swing.JLabel();
|
||||||
|
currPageLabel = new javax.swing.JLabel();
|
||||||
|
jLabel3 = new javax.swing.JLabel();
|
||||||
|
numPagesLabel = new javax.swing.JLabel();
|
||||||
|
prevPageButton = new javax.swing.JButton();
|
||||||
|
nextPageButton = new javax.swing.JButton();
|
||||||
jTableDataPanel = new javax.swing.JPanel();
|
jTableDataPanel = new javax.swing.JPanel();
|
||||||
jScrollPane1 = new javax.swing.JScrollPane();
|
|
||||||
jTable1 = new javax.swing.JTable();
|
jHdrPanel.setPreferredSize(new java.awt.Dimension(536, 40));
|
||||||
|
|
||||||
tablesDropdownList.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
|
tablesDropdownList.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
|
||||||
tablesDropdownList.addActionListener(new java.awt.event.ActionListener() {
|
tablesDropdownList.addActionListener(new java.awt.event.ActionListener() {
|
||||||
@ -89,9 +108,38 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
|
|||||||
numEntriesField.setEditable(false);
|
numEntriesField.setEditable(false);
|
||||||
numEntriesField.setText(org.openide.util.NbBundle.getMessage(SQLiteViewer.class, "SQLiteViewer.numEntriesField.text")); // NOI18N
|
numEntriesField.setText(org.openide.util.NbBundle.getMessage(SQLiteViewer.class, "SQLiteViewer.numEntriesField.text")); // NOI18N
|
||||||
numEntriesField.setBorder(null);
|
numEntriesField.setBorder(null);
|
||||||
numEntriesField.addActionListener(new java.awt.event.ActionListener() {
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(SQLiteViewer.class, "SQLiteViewer.jLabel2.text")); // NOI18N
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(currPageLabel, org.openide.util.NbBundle.getMessage(SQLiteViewer.class, "SQLiteViewer.currPageLabel.text")); // NOI18N
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(SQLiteViewer.class, "SQLiteViewer.jLabel3.text")); // NOI18N
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(numPagesLabel, org.openide.util.NbBundle.getMessage(SQLiteViewer.class, "SQLiteViewer.numPagesLabel.text")); // NOI18N
|
||||||
|
|
||||||
|
prevPageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back.png"))); // NOI18N
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(prevPageButton, org.openide.util.NbBundle.getMessage(SQLiteViewer.class, "SQLiteViewer.prevPageButton.text")); // NOI18N
|
||||||
|
prevPageButton.setBorderPainted(false);
|
||||||
|
prevPageButton.setContentAreaFilled(false);
|
||||||
|
prevPageButton.setDisabledSelectedIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back_disabled.png"))); // NOI18N
|
||||||
|
prevPageButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
|
||||||
|
prevPageButton.setPreferredSize(new java.awt.Dimension(23, 23));
|
||||||
|
prevPageButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
numEntriesFieldActionPerformed(evt);
|
prevPageButtonActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
nextPageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png"))); // NOI18N
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(nextPageButton, org.openide.util.NbBundle.getMessage(SQLiteViewer.class, "SQLiteViewer.nextPageButton.text")); // NOI18N
|
||||||
|
nextPageButton.setBorderPainted(false);
|
||||||
|
nextPageButton.setContentAreaFilled(false);
|
||||||
|
nextPageButton.setDisabledSelectedIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward_disabled.png"))); // NOI18N
|
||||||
|
nextPageButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
|
||||||
|
nextPageButton.setPreferredSize(new java.awt.Dimension(23, 23));
|
||||||
|
nextPageButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
nextPageButtonActionPerformed(evt);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -102,53 +150,44 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
|
|||||||
.addGroup(jHdrPanelLayout.createSequentialGroup()
|
.addGroup(jHdrPanelLayout.createSequentialGroup()
|
||||||
.addContainerGap()
|
.addContainerGap()
|
||||||
.addComponent(jLabel1)
|
.addComponent(jLabel1)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(tablesDropdownList, javax.swing.GroupLayout.PREFERRED_SIZE, 130, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(tablesDropdownList, javax.swing.GroupLayout.PREFERRED_SIZE, 130, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addGap(23, 23, 23)
|
.addGap(18, 18, 18)
|
||||||
.addComponent(numEntriesField, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(numEntriesField, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addContainerGap(130, Short.MAX_VALUE))
|
.addGap(15, 15, 15)
|
||||||
|
.addComponent(jLabel2)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(currPageLabel)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(jLabel3)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(numPagesLabel)
|
||||||
|
.addGap(18, 18, 18)
|
||||||
|
.addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addGap(0, 0, 0)
|
||||||
|
.addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addContainerGap(133, Short.MAX_VALUE))
|
||||||
);
|
);
|
||||||
jHdrPanelLayout.setVerticalGroup(
|
jHdrPanelLayout.setVerticalGroup(
|
||||||
jHdrPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
jHdrPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGroup(jHdrPanelLayout.createSequentialGroup()
|
.addGroup(jHdrPanelLayout.createSequentialGroup()
|
||||||
.addContainerGap()
|
.addContainerGap()
|
||||||
.addGroup(jHdrPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
.addGroup(jHdrPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(tablesDropdownList, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addComponent(jLabel1)
|
.addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addComponent(numEntriesField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
.addGroup(jHdrPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||||
.addContainerGap(16, Short.MAX_VALUE))
|
.addComponent(tablesDropdownList, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
);
|
.addComponent(jLabel1)
|
||||||
|
.addComponent(numEntriesField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
jTable1.setModel(new javax.swing.table.DefaultTableModel(
|
.addComponent(jLabel2)
|
||||||
new Object [][] {
|
.addComponent(currPageLabel)
|
||||||
{null, null, null, null},
|
.addComponent(jLabel3)
|
||||||
{null, null, null, null},
|
.addComponent(numPagesLabel)))
|
||||||
{null, null, null, null},
|
|
||||||
{null, null, null, null}
|
|
||||||
},
|
|
||||||
new String [] {
|
|
||||||
"Title 1", "Title 2", "Title 3", "Title 4"
|
|
||||||
}
|
|
||||||
));
|
|
||||||
jScrollPane1.setViewportView(jTable1);
|
|
||||||
|
|
||||||
javax.swing.GroupLayout jTableDataPanelLayout = new javax.swing.GroupLayout(jTableDataPanel);
|
|
||||||
jTableDataPanel.setLayout(jTableDataPanelLayout);
|
|
||||||
jTableDataPanelLayout.setHorizontalGroup(
|
|
||||||
jTableDataPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
||||||
.addGroup(jTableDataPanelLayout.createSequentialGroup()
|
|
||||||
.addContainerGap()
|
|
||||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
|
|
||||||
.addGap(15, 15, 15))
|
|
||||||
);
|
|
||||||
jTableDataPanelLayout.setVerticalGroup(
|
|
||||||
jTableDataPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
||||||
.addGroup(jTableDataPanelLayout.createSequentialGroup()
|
|
||||||
.addContainerGap()
|
|
||||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 275, Short.MAX_VALUE)
|
|
||||||
.addContainerGap())
|
.addContainerGap())
|
||||||
);
|
);
|
||||||
|
|
||||||
|
jTableDataPanel.setLayout(new java.awt.BorderLayout());
|
||||||
|
|
||||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||||
this.setLayout(layout);
|
this.setLayout(layout);
|
||||||
layout.setHorizontalGroup(
|
layout.setHorizontalGroup(
|
||||||
@ -159,34 +198,62 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
|
|||||||
layout.setVerticalGroup(
|
layout.setVerticalGroup(
|
||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGroup(layout.createSequentialGroup()
|
.addGroup(layout.createSequentialGroup()
|
||||||
.addComponent(jHdrPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(jHdrPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 53, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
.addGap(0, 0, 0)
|
||||||
.addComponent(jTableDataPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
.addComponent(jTableDataPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 317, Short.MAX_VALUE))
|
||||||
);
|
);
|
||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
private void numEntriesFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_numEntriesFieldActionPerformed
|
private void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextPageButtonActionPerformed
|
||||||
// TODO add your handling code here:
|
|
||||||
}//GEN-LAST:event_numEntriesFieldActionPerformed
|
currPage++;
|
||||||
|
if (currPage * ROWS_PER_PAGE > numRows) {
|
||||||
|
nextPageButton.setEnabled(false);
|
||||||
|
}
|
||||||
|
currPageLabel.setText(Integer.toString(currPage));
|
||||||
|
prevPageButton.setEnabled(true);
|
||||||
|
|
||||||
|
// read and display a page of rows
|
||||||
|
String tableName = (String) this.tablesDropdownList.getSelectedItem();
|
||||||
|
readTable(tableName, (currPage - 1) * ROWS_PER_PAGE + 1, ROWS_PER_PAGE);
|
||||||
|
}//GEN-LAST:event_nextPageButtonActionPerformed
|
||||||
|
|
||||||
|
private void prevPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_prevPageButtonActionPerformed
|
||||||
|
|
||||||
|
currPage--;
|
||||||
|
if (currPage == 1) {
|
||||||
|
prevPageButton.setEnabled(false);
|
||||||
|
}
|
||||||
|
currPageLabel.setText(Integer.toString(currPage));
|
||||||
|
nextPageButton.setEnabled(true);
|
||||||
|
|
||||||
|
// read and display a page of rows
|
||||||
|
String tableName = (String) this.tablesDropdownList.getSelectedItem();
|
||||||
|
readTable(tableName, (currPage - 1) * ROWS_PER_PAGE + 1, ROWS_PER_PAGE);
|
||||||
|
}//GEN-LAST:event_prevPageButtonActionPerformed
|
||||||
|
|
||||||
private void tablesDropdownListActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tablesDropdownListActionPerformed
|
private void tablesDropdownListActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tablesDropdownListActionPerformed
|
||||||
JComboBox<String> cb = (JComboBox<String>) evt.getSource();
|
JComboBox<?> cb = (JComboBox<?>) evt.getSource();
|
||||||
String tableName = (String) cb.getSelectedItem();
|
String tableName = (String) cb.getSelectedItem();
|
||||||
if (null == tableName) {
|
if (null == tableName) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
readTable(tableName);
|
selectTable(tableName);
|
||||||
}//GEN-LAST:event_tablesDropdownListActionPerformed
|
}//GEN-LAST:event_tablesDropdownListActionPerformed
|
||||||
|
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
private javax.swing.JLabel currPageLabel;
|
||||||
private javax.swing.JPanel jHdrPanel;
|
private javax.swing.JPanel jHdrPanel;
|
||||||
private javax.swing.JLabel jLabel1;
|
private javax.swing.JLabel jLabel1;
|
||||||
private javax.swing.JScrollPane jScrollPane1;
|
private javax.swing.JLabel jLabel2;
|
||||||
private javax.swing.JTable jTable1;
|
private javax.swing.JLabel jLabel3;
|
||||||
private javax.swing.JPanel jTableDataPanel;
|
private javax.swing.JPanel jTableDataPanel;
|
||||||
|
private javax.swing.JButton nextPageButton;
|
||||||
private javax.swing.JTextField numEntriesField;
|
private javax.swing.JTextField numEntriesField;
|
||||||
|
private javax.swing.JLabel numPagesLabel;
|
||||||
|
private javax.swing.JButton prevPageButton;
|
||||||
private javax.swing.JComboBox<String> tablesDropdownList;
|
private javax.swing.JComboBox<String> tablesDropdownList;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
@ -231,11 +298,6 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void customizeComponents() {
|
|
||||||
|
|
||||||
// add a actionListener to jTablesComboBox
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process the given SQLite DB file
|
* Process the given SQLite DB file
|
||||||
*
|
*
|
||||||
@ -256,7 +318,7 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
|
|||||||
tmpDBPathName = Case.getCurrentCase().getTempDirectory() + File.separator + sqliteFile.getName() + "-" + sqliteFile.getId();
|
tmpDBPathName = Case.getCurrentCase().getTempDirectory() + File.separator + sqliteFile.getName() + "-" + sqliteFile.getId();
|
||||||
tmpDBFile = new File(tmpDBPathName);
|
tmpDBFile = new File(tmpDBPathName);
|
||||||
ContentUtils.writeToFile(sqliteFile, tmpDBFile);
|
ContentUtils.writeToFile(sqliteFile, tmpDBFile);
|
||||||
|
|
||||||
// Open copy using JDBC
|
// Open copy using JDBC
|
||||||
Class.forName("org.sqlite.JDBC"); //NON-NLS //load JDBC driver
|
Class.forName("org.sqlite.JDBC"); //NON-NLS //load JDBC driver
|
||||||
connection = DriverManager.getConnection("jdbc:sqlite:" + tmpDBPathName); //NON-NLS
|
connection = DriverManager.getConnection("jdbc:sqlite:" + tmpDBPathName); //NON-NLS
|
||||||
@ -315,42 +377,28 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
|
|||||||
String tableSQL = resultSet.getString("sql"); //NON-NLS
|
String tableSQL = resultSet.getString("sql"); //NON-NLS
|
||||||
|
|
||||||
dbTablesMap.put(tableName, tableSQL);
|
dbTablesMap.put(tableName, tableSQL);
|
||||||
String query = "PRAGMA table_info(" + tableName + ")"; //NON-NLS
|
|
||||||
ResultSet rs2;
|
|
||||||
try {
|
|
||||||
Statement statement2 = connection.createStatement();
|
|
||||||
rs2 = statement2.executeQuery(query);
|
|
||||||
while (rs2.next()) {
|
|
||||||
|
|
||||||
// System.out.println("RAMAN: Col Name = " + rs2.getString("name"));
|
|
||||||
// System.out.println("RAMAN: Col Type = " + rs2.getString("type"));
|
|
||||||
|
|
||||||
// RAMAN TBD: parse and save the table schema
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
|
||||||
LOGGER.log(Level.WARNING, "Error while trying to get columns from sqlite db." + connection, ex); //NON-NLS
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (SQLException e) {
|
||||||
LOGGER.log(Level.SEVERE, "Error getting table names from the DB", e); //NON-NLS
|
LOGGER.log(Level.SEVERE, "Error getting table names from the DB", e); //NON-NLS
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readTable(String tableName) {
|
private void selectTable(String tableName) {
|
||||||
// TBD: need to handle cancelling if one is already in progress
|
if (worker != null && !worker.isDone()) {
|
||||||
|
worker.cancel(false);
|
||||||
new SwingWorker<Integer, Void>() {
|
worker = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
worker = new SwingWorker<Integer, Void>() {
|
||||||
@Override
|
@Override
|
||||||
protected Integer doInBackground() throws Exception {
|
protected Integer doInBackground() throws Exception {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Statement statement = connection.createStatement();
|
Statement statement = connection.createStatement();
|
||||||
ResultSet resultSet = statement.executeQuery(
|
ResultSet resultSet = statement.executeQuery(
|
||||||
"SELECT COUNT(*) as count FROM " + tableName); //NON-NLS
|
"SELECT count (*) as count FROM " + tableName); //NON-NLS
|
||||||
|
|
||||||
// TBD: read the rows here and popluate the ExplorerManager.
|
|
||||||
|
|
||||||
return resultSet.getInt("count");
|
return resultSet.getInt("count");
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Failed to get data for table.", ex); //NON-NLS
|
LOGGER.log(Level.SEVERE, "Failed to get data for table.", ex); //NON-NLS
|
||||||
@ -363,33 +411,104 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
|
|||||||
protected void done() {
|
protected void done() {
|
||||||
super.done();
|
super.done();
|
||||||
try {
|
try {
|
||||||
int numRows = get();
|
|
||||||
|
numRows = get();
|
||||||
numEntriesField.setText(numRows + " entries");
|
numEntriesField.setText(numRows + " entries");
|
||||||
|
|
||||||
|
currPage = 1;
|
||||||
|
currPageLabel.setText(Integer.toString(currPage));
|
||||||
|
numPagesLabel.setText(Integer.toString((numRows / ROWS_PER_PAGE) + 1));
|
||||||
|
|
||||||
|
prevPageButton.setEnabled(false);
|
||||||
|
|
||||||
|
|
||||||
|
if (numRows > 0) {
|
||||||
|
nextPageButton.setEnabled(((numRows > ROWS_PER_PAGE)));
|
||||||
|
readTable(tableName, (currPage - 1) * ROWS_PER_PAGE + 1, ROWS_PER_PAGE);
|
||||||
|
} else {
|
||||||
|
nextPageButton.setEnabled(false);
|
||||||
|
selectedTableView.setupTable(Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
} catch (InterruptedException | ExecutionException ex) {
|
} catch (InterruptedException | ExecutionException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Unexpected exception while reading table.", ex); //NON-NLS
|
LOGGER.log(Level.SEVERE, "Unexpected exception while reading table.", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.execute();
|
};
|
||||||
|
worker.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SQLStorageClass {
|
private void readTable(String tableName, int startRow, int numRowsToRead) {
|
||||||
NULL,
|
|
||||||
INTEGER,
|
|
||||||
REAL,
|
|
||||||
TEXT,
|
|
||||||
BLOB
|
|
||||||
};
|
|
||||||
|
|
||||||
private class SQLColDef {
|
if (worker != null && !worker.isDone()) {
|
||||||
|
worker.cancel(false);
|
||||||
private final String colName;
|
worker = null;
|
||||||
private final SQLStorageClass storageClass;
|
|
||||||
|
|
||||||
SQLColDef(String colName, SQLStorageClass sc) {
|
|
||||||
this.colName = colName;
|
|
||||||
this.storageClass = sc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
worker = new SwingWorker<ArrayList<Map<String, Object>>, Void>() {
|
||||||
|
@Override
|
||||||
|
protected ArrayList<Map<String, Object>> doInBackground() throws Exception {
|
||||||
|
try {
|
||||||
|
Statement statement = connection.createStatement();
|
||||||
|
ResultSet resultSet = statement.executeQuery(
|
||||||
|
"SELECT * FROM " + tableName
|
||||||
|
+ " LIMIT " + Integer.toString(numRowsToRead)
|
||||||
|
+ " OFFSET " + Integer.toString(startRow - 1)
|
||||||
|
); //NON-NLS
|
||||||
|
|
||||||
|
return resultSetToArrayList(resultSet);
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
LOGGER.log(Level.SEVERE, "Failed to get data for table " + tableName, ex); //NON-NLS
|
||||||
|
}
|
||||||
|
//NON-NLS
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void done() {
|
||||||
|
|
||||||
|
if (isCancelled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.done();
|
||||||
|
try {
|
||||||
|
ArrayList<Map<String, Object>> rows = get();
|
||||||
|
if (Objects.nonNull(rows)) {
|
||||||
|
selectedTableView.setupTable(rows);
|
||||||
|
}else{
|
||||||
|
selectedTableView.setupTable(Collections.emptyList());
|
||||||
|
}
|
||||||
|
} catch (InterruptedException | ExecutionException ex) {
|
||||||
|
LOGGER.log(Level.SEVERE, "Unexpected exception while reading table " + tableName, ex); //NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
worker.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NbBundle.Messages("SQLiteViewer.BlobNotShown.message=BLOB Data not shown")
|
||||||
|
private ArrayList<Map<String, Object>> resultSetToArrayList(ResultSet rs) throws SQLException {
|
||||||
|
ResultSetMetaData metaData = rs.getMetaData();
|
||||||
|
int columns = metaData.getColumnCount();
|
||||||
|
ArrayList<Map<String, Object>> rowlist = new ArrayList<>();
|
||||||
|
while (rs.next()) {
|
||||||
|
Map<String, Object> row = new LinkedHashMap<>(columns);
|
||||||
|
for (int i = 1; i <= columns; ++i) {
|
||||||
|
if (rs.getObject(i) == null) {
|
||||||
|
row.put(metaData.getColumnName(i), "");
|
||||||
|
} else {
|
||||||
|
if (metaData.getColumnTypeName(i).compareToIgnoreCase("blob") == 0) {
|
||||||
|
row.put(metaData.getColumnName(i), Bundle.SQLiteViewer_BlobNotShown_message());
|
||||||
|
} else {
|
||||||
|
row.put(metaData.getColumnName(i), rs.getObject(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rowlist.add(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rowlist;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user