mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-15 17:27:43 +00:00
bug fixes
This commit is contained in:
parent
e0351c7c0a
commit
78d69f173b
@ -108,7 +108,24 @@ final class DataSourceInfoUtilities {
|
|||||||
* obtained.
|
* obtained.
|
||||||
*/
|
*/
|
||||||
static <T> T getBaseQueryResult(String query, ResultSetHandler<T> processor, String errorMessage) {
|
static <T> T getBaseQueryResult(String query, ResultSetHandler<T> processor, String errorMessage) {
|
||||||
try (SleuthkitCase.CaseDbQuery dbQuery = Case.getCurrentCaseThrows().getSleuthkitCase().executeQuery(query)) {
|
return getBaseQueryResult(SleuthkitCaseProvider.DEFAULT, query, processor, errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a result based on the provided query.
|
||||||
|
*
|
||||||
|
* @param provider The means of obtaining a SleuthkitCase.
|
||||||
|
* @param query The query.
|
||||||
|
* @param processor The result set handler.
|
||||||
|
* @param errorMessage The error message to display if there is an error
|
||||||
|
* retrieving the resultset.
|
||||||
|
*
|
||||||
|
* @return The ResultSetHandler value or null if no ResultSet could be
|
||||||
|
* obtained.
|
||||||
|
*/
|
||||||
|
static <T> T getBaseQueryResult(SleuthkitCaseProvider provider, String query, ResultSetHandler<T> processor, String errorMessage) {
|
||||||
|
try (SleuthkitCase.CaseDbQuery dbQuery = provider.get().executeQuery(query)) {
|
||||||
ResultSet resultSet = dbQuery.getResultSet();
|
ResultSet resultSet = dbQuery.getResultSet();
|
||||||
try {
|
try {
|
||||||
return processor.process(resultSet);
|
return processor.process(resultSet);
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2020 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.datasourcesummary.datamodel;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
import org.sleuthkit.datamodel.DataSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides summary information about top domains in a datasource.
|
||||||
|
*/
|
||||||
|
public class DataSourceTopDomainsSummary {
|
||||||
|
private static final long SLEEP_TIME = 5000;
|
||||||
|
|
||||||
|
// private final SleuthkitCaseProvider provider;
|
||||||
|
//
|
||||||
|
// public DataSourceTopDomainsSummary() {
|
||||||
|
// this(SleuthkitCaseProvider.DEFAULT);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public DataSourceTopDomainsSummary(SleuthkitCaseProvider provider) {
|
||||||
|
// this.provider = provider;
|
||||||
|
// }
|
||||||
|
|
||||||
|
interface Function2<A1,A2,O> {
|
||||||
|
O apply(A1 a1, A2 a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TopDomainsResult> getRecentDomains(DataSource dataSource, int count) throws InterruptedException {
|
||||||
|
Thread.sleep(SLEEP_TIME);
|
||||||
|
final String dId = Long.toString(dataSource.getId());
|
||||||
|
final Function2<String, Integer, String> getId = (s,idx) -> String.format("d:%s, f:%s, i:%d", dId, s, idx);
|
||||||
|
return IntStream.range(0, count)
|
||||||
|
.mapToObj(num -> new TopDomainsResult(
|
||||||
|
getId.apply("domain", num),
|
||||||
|
getId.apply("url", num),
|
||||||
|
(long)num,
|
||||||
|
new Date(120, 1, num)
|
||||||
|
))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
@ -66,6 +66,36 @@ public class DataSourceTopProgramsSummary {
|
|||||||
*/
|
*/
|
||||||
private static final String QUERY_SUFFIX = "_query";
|
private static final String QUERY_SUFFIX = "_query";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functions that determine the folder name of a list of path elements. If
|
||||||
|
* not matched, function returns null.
|
||||||
|
*/
|
||||||
|
private static final List<Function<List<String>, String>> SHORT_FOLDER_MATCHERS = Arrays.asList(
|
||||||
|
// handle Program Files and Program Files (x86) - if true, return the next folder
|
||||||
|
(pathList) -> {
|
||||||
|
if (pathList.size() < 2) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String rootParent = pathList.get(0).toUpperCase();
|
||||||
|
if ("PROGRAM FILES".equals(rootParent) || "PROGRAM FILES (X86)".equals(rootParent)) {
|
||||||
|
return pathList.get(1);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// if there is a folder named "APPLICATION DATA" or "APPDATA"
|
||||||
|
(pathList) -> {
|
||||||
|
for (String pathEl : pathList) {
|
||||||
|
String uppered = pathEl.toUpperCase();
|
||||||
|
if ("APPLICATION DATA".equals(uppered) || "APPDATA".equals(uppered)) {
|
||||||
|
return "AppData";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a sql statement querying the blackboard attributes table for a
|
* Creates a sql statement querying the blackboard attributes table for a
|
||||||
* particular attribute type and returning a specified value. That query
|
* particular attribute type and returning a specified value. That query
|
||||||
@ -139,6 +169,17 @@ public class DataSourceTopProgramsSummary {
|
|||||||
return column + (isLike ? "" : " NOT") + " LIKE '" + likeString + "'";
|
return column + (isLike ? "" : " NOT") + " LIKE '" + likeString + "'";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private final SleuthkitCaseProvider provider;
|
||||||
|
|
||||||
|
public DataSourceTopProgramsSummary() {
|
||||||
|
this(SleuthkitCaseProvider.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataSourceTopProgramsSummary(SleuthkitCaseProvider provider) {
|
||||||
|
this.provider = provider;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves a list of the top programs used on the data source. Currently
|
* Retrieves a list of the top programs used on the data source. Currently
|
||||||
* determines this based off of which prefetch results return the highest
|
* determines this based off of which prefetch results return the highest
|
||||||
@ -149,7 +190,7 @@ public class DataSourceTopProgramsSummary {
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static List<TopProgramsResult> getTopPrograms(DataSource dataSource, int count) {
|
public List<TopProgramsResult> getTopPrograms(DataSource dataSource, int count) {
|
||||||
if (dataSource == null || count <= 0) {
|
if (dataSource == null || count <= 0) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
@ -225,38 +266,9 @@ public class DataSourceTopProgramsSummary {
|
|||||||
return progResults;
|
return progResults;
|
||||||
};
|
};
|
||||||
|
|
||||||
return getBaseQueryResult(query, handler, errorMessage);
|
return getBaseQueryResult(provider, query, handler, errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Functions that determine the folder name of a list of path elements. If
|
|
||||||
* not matched, function returns null.
|
|
||||||
*/
|
|
||||||
private static final List<Function<List<String>, String>> SHORT_FOLDER_MATCHERS = Arrays.asList(
|
|
||||||
// handle Program Files and Program Files (x86) - if true, return the next folder
|
|
||||||
(pathList) -> {
|
|
||||||
if (pathList.size() < 2) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
String rootParent = pathList.get(0).toUpperCase();
|
|
||||||
if ("PROGRAM FILES".equals(rootParent) || "PROGRAM FILES (X86)".equals(rootParent)) {
|
|
||||||
return pathList.get(1);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// if there is a folder named "APPLICATION DATA" or "APPDATA"
|
|
||||||
(pathList) -> {
|
|
||||||
for (String pathEl : pathList) {
|
|
||||||
String uppered = pathEl.toUpperCase();
|
|
||||||
if ("APPLICATION DATA".equals(uppered) || "APPDATA".equals(uppered)) {
|
|
||||||
return "AppData";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines a short folder name if any. Otherwise, returns empty string.
|
* Determines a short folder name if any. Otherwise, returns empty string.
|
||||||
@ -289,7 +301,4 @@ public class DataSourceTopProgramsSummary {
|
|||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataSourceTopProgramsSummary() {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2020 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.datasourcesummary.datamodel;
|
||||||
|
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface to provide the current SleuthkitCase object. By default, this
|
||||||
|
* uses Case.getCurrentCaseThrows().getSleuthkkitCase().
|
||||||
|
*/
|
||||||
|
public interface SleuthkitCaseProvider {
|
||||||
|
public static final SleuthkitCaseProvider DEFAULT = () -> Case.getCurrentCaseThrows().getSleuthkitCase();
|
||||||
|
|
||||||
|
SleuthkitCase get() throws NoCurrentCaseException;
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2020 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.datasourcesummary.datamodel;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes a result of a program run on a datasource.
|
||||||
|
*/
|
||||||
|
public class TopDomainsResult {
|
||||||
|
|
||||||
|
private final String domain;
|
||||||
|
private final String url;
|
||||||
|
private final Long visitTimes;
|
||||||
|
private final Date lastVisit;
|
||||||
|
|
||||||
|
public TopDomainsResult(String domain, String url, Long visitTimes, Date lastVisit) {
|
||||||
|
this.domain = domain;
|
||||||
|
this.url = url;
|
||||||
|
this.visitTimes = visitTimes;
|
||||||
|
this.lastVisit = lastVisit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDomain() {
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getVisitTimes() {
|
||||||
|
return visitTimes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getLastVisit() {
|
||||||
|
return lastVisit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -35,4 +35,5 @@ DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text=Unallocated Space:
|
|||||||
DataSourceSummaryDetailsPanel.unallocatedSizeValue.text=
|
DataSourceSummaryDetailsPanel.unallocatedSizeValue.text=
|
||||||
DataSourceSummaryCountsPanel.byCategoryLabel.text=Files by Category
|
DataSourceSummaryCountsPanel.byCategoryLabel.text=Files by Category
|
||||||
DataSourceSummaryCountsPanel.resultsByTypeLabel.text=Results by Type
|
DataSourceSummaryCountsPanel.resultsByTypeLabel.text=Results by Type
|
||||||
DataSourceSummaryUserActivityPanel.programsRunLabel.text=Top Programs Run
|
DataSourceSummaryUserActivityPanel.programsRunLabel.text=Recent Programs
|
||||||
|
DataSourceSummaryUserActivityPanel.recentDomainsLabel.text=Recent Domains
|
||||||
|
@ -75,8 +75,12 @@ DataSourceSummaryTabbedPane_countsTab_title=Counts
|
|||||||
DataSourceSummaryTabbedPane_detailsTab_title=Details
|
DataSourceSummaryTabbedPane_detailsTab_title=Details
|
||||||
DataSourceSummaryTabbedPane_ingestHistoryTab_title=Ingest History
|
DataSourceSummaryTabbedPane_ingestHistoryTab_title=Ingest History
|
||||||
DataSourceSummaryTabbedPane_userActivityTab_title=User Activity
|
DataSourceSummaryTabbedPane_userActivityTab_title=User Activity
|
||||||
DataSourceSummaryUserActivityPanel.programsRunLabel.text=Top Programs Run
|
DataSourceSummaryUserActivityPanel.programsRunLabel.text=Recent Programs
|
||||||
|
DataSourceSummaryUserActivityPanel.recentDomainsLabel.text=Recent Domains
|
||||||
DataSourceSummaryUserActivityPanel_tab_title=User Activity
|
DataSourceSummaryUserActivityPanel_tab_title=User Activity
|
||||||
|
DataSourceSummaryUserActivityPanel_TopDomainsTableModel_domain_header=Domain
|
||||||
|
DataSourceSummaryUserActivityPanel_TopDomainsTableModel_lastAccess_header=Last Access
|
||||||
|
DataSourceSummaryUserActivityPanel_TopDomainsTableModel_url_header=URL
|
||||||
DataSourceSummaryUserActivityPanel_TopProgramsTableModel_count_header=Run Times
|
DataSourceSummaryUserActivityPanel_TopProgramsTableModel_count_header=Run Times
|
||||||
DataSourceSummaryUserActivityPanel_TopProgramsTableModel_folder_header=Folder
|
DataSourceSummaryUserActivityPanel_TopProgramsTableModel_folder_header=Folder
|
||||||
DataSourceSummaryUserActivityPanel_TopProgramsTableModel_lastrun_header=Last Run
|
DataSourceSummaryUserActivityPanel_TopProgramsTableModel_lastrun_header=Last Run
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
<?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.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
|
<Properties>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="null"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
<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"/>
|
||||||
@ -11,59 +16,180 @@
|
|||||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
<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,-58,0,0,2,-42"/>
|
||||||
</AuxValues>
|
</AuxValues>
|
||||||
|
|
||||||
<Layout>
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||||
<DimensionLayout dim="0">
|
<SubComponents>
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Container class="javax.swing.JScrollPane" name="contentScrollPane">
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Properties>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Dimension value="null"/>
|
||||||
<Component id="programsRunLabel" min="-2" pref="155" max="-2" attributes="0"/>
|
</Property>
|
||||||
<Component id="topProgramsScrollPane" min="-2" pref="460" max="-2" attributes="0"/>
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
</Group>
|
<Dimension value="null"/>
|
||||||
<EmptySpace pref="128" max="32767" attributes="0"/>
|
</Property>
|
||||||
</Group>
|
</Properties>
|
||||||
</Group>
|
<AuxValues>
|
||||||
</DimensionLayout>
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
<DimensionLayout dim="1">
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
</AuxValues>
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Constraints>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
|
||||||
<Component id="programsRunLabel" min="-2" max="-2" attributes="0"/>
|
<BorderConstraints direction="Center"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
</Constraint>
|
||||||
<Component id="topProgramsScrollPane" min="-2" max="-2" attributes="0"/>
|
</Constraints>
|
||||||
<EmptySpace max="32767" attributes="0"/>
|
|
||||||
</Group>
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||||
</Group>
|
<SubComponents>
|
||||||
</DimensionLayout>
|
<Container class="javax.swing.JPanel" name="contentPanel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||||
|
<Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
|
||||||
|
<EmptyBorder bottom="10" left="10" right="10" top="10"/>
|
||||||
|
</Border>
|
||||||
|
</Property>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[720, 450]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[720, 450]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
|
||||||
|
<Property name="axis" type="int" value="3"/>
|
||||||
</Layout>
|
</Layout>
|
||||||
<SubComponents>
|
<SubComponents>
|
||||||
<Component class="javax.swing.JLabel" name="programsRunLabel">
|
<Component class="javax.swing.JLabel" name="programsRunLabel">
|
||||||
<Properties>
|
<Properties>
|
||||||
|
<Property name="horizontalAlignment" type="int" value="2"/>
|
||||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryUserActivityPanel.programsRunLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryUserActivityPanel.programsRunLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
</Property>
|
</Property>
|
||||||
|
<Property name="alignmentX" type="float" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||||
|
<Connection code="Component.LEFT_ALIGNMENT" type="code"/>
|
||||||
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
<AuxValues>
|
<AuxValues>
|
||||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
</AuxValues>
|
</AuxValues>
|
||||||
</Component>
|
</Component>
|
||||||
<Container class="javax.swing.JScrollPane" name="topProgramsScrollPane">
|
<Component class="javax.swing.Box$Filler" name="filler1">
|
||||||
<Properties>
|
<Properties>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 2]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 2]"/>
|
||||||
|
</Property>
|
||||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
<Dimension value="[750, 187]"/>
|
<Dimension value="[0, 2]"/>
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
<AuxValues>
|
<AuxValues>
|
||||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.RigidArea"/>
|
||||||
|
</AuxValues>
|
||||||
|
</Component>
|
||||||
|
<Container class="javax.swing.JPanel" name="topProgramsTablePanel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="alignmentX" type="float" value="0.0"/>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[700, 187]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[700, 187]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[700, 187]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="topProgramsTable"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
</AuxValues>
|
</AuxValues>
|
||||||
|
|
||||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
|
||||||
<SubComponents>
|
</Container>
|
||||||
<Component class="javax.swing.JTable" name="topProgramsTable">
|
<Component class="javax.swing.Box$Filler" name="filler3">
|
||||||
|
<Properties>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 20]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 20]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 20]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.RigidArea"/>
|
||||||
|
</AuxValues>
|
||||||
</Component>
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="recentDomainsLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="horizontalAlignment" type="int" value="2"/>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryUserActivityPanel.recentDomainsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.Box$Filler" name="filler2">
|
||||||
|
<Properties>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 2]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 2]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 2]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.RigidArea"/>
|
||||||
|
</AuxValues>
|
||||||
|
</Component>
|
||||||
|
<Container class="javax.swing.JPanel" name="recentDomainsTablePanel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="alignmentX" type="float" value="0.0"/>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[700, 187]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[700, 187]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[700, 187]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="recentDomainsTable"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
|
@ -21,20 +21,26 @@ package org.sleuthkit.autopsy.datasourcesummary.ui;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import javax.swing.JLabel;
|
import java.util.stream.Collectors;
|
||||||
import javax.swing.JTable;
|
|
||||||
import javax.swing.table.AbstractTableModel;
|
|
||||||
import javax.swing.table.DefaultTableCellRenderer;
|
|
||||||
import javax.swing.table.TableCellRenderer;
|
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceTopDomainsSummary;
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceTopProgramsSummary;
|
import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceTopProgramsSummary;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.datamodel.TopDomainsResult;
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.datamodel.TopProgramsResult;
|
import org.sleuthkit.autopsy.datasourcesummary.datamodel.TopProgramsResult;
|
||||||
|
import org.sleuthkit.autopsy.guiutils.internal.DataFetchWorker;
|
||||||
|
import org.sleuthkit.autopsy.guiutils.internal.DataFetchWorker.DataFetchComponents;
|
||||||
|
import org.sleuthkit.autopsy.guiutils.internal.DataLoadingResult;
|
||||||
|
import org.sleuthkit.autopsy.guiutils.internal.DataResultJTable;
|
||||||
|
import org.sleuthkit.autopsy.guiutils.internal.DefaultPojoListTableDataModel;
|
||||||
|
import org.sleuthkit.autopsy.guiutils.internal.DefaultPojoListTableDataModel.DefaultCellModel;
|
||||||
|
import org.sleuthkit.autopsy.guiutils.internal.DefaultPojoListTableDataModel.DefaultColumnModel;
|
||||||
|
import org.sleuthkit.autopsy.guiutils.internal.DefaultPojoListTableDataModel.HorizontalAlign;
|
||||||
import org.sleuthkit.datamodel.DataSource;
|
import org.sleuthkit.datamodel.DataSource;
|
||||||
|
import org.sleuthkit.autopsy.guiutils.internal.SwingWorkerSequentialRunner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A panel to display user activity.
|
* A panel to display user activity.
|
||||||
@ -44,18 +50,21 @@ import org.sleuthkit.datamodel.DataSource;
|
|||||||
"DataSourceSummaryUserActivityPanel_TopProgramsTableModel_name_header=Program",
|
"DataSourceSummaryUserActivityPanel_TopProgramsTableModel_name_header=Program",
|
||||||
"DataSourceSummaryUserActivityPanel_TopProgramsTableModel_folder_header=Folder",
|
"DataSourceSummaryUserActivityPanel_TopProgramsTableModel_folder_header=Folder",
|
||||||
"DataSourceSummaryUserActivityPanel_TopProgramsTableModel_count_header=Run Times",
|
"DataSourceSummaryUserActivityPanel_TopProgramsTableModel_count_header=Run Times",
|
||||||
"DataSourceSummaryUserActivityPanel_TopProgramsTableModel_lastrun_header=Last Run"
|
"DataSourceSummaryUserActivityPanel_TopProgramsTableModel_lastrun_header=Last Run",
|
||||||
})
|
"DataSourceSummaryUserActivityPanel_TopDomainsTableModel_domain_header=Domain",
|
||||||
|
"DataSourceSummaryUserActivityPanel_TopDomainsTableModel_url_header=URL",
|
||||||
|
"DataSourceSummaryUserActivityPanel_TopDomainsTableModel_lastAccess_header=Last Access",})
|
||||||
public class DataSourceSummaryUserActivityPanel extends javax.swing.JPanel {
|
public class DataSourceSummaryUserActivityPanel extends javax.swing.JPanel {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private static final DateFormat DATETIME_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.getDefault());
|
private static final DateFormat DATETIME_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.getDefault());
|
||||||
private static final int TOP_PROGS_COUNT = 10;
|
private static final int TOP_PROGS_COUNT = 10;
|
||||||
private static final DefaultTableCellRenderer RIGHT_ALIGNED_RENDERER = new DefaultTableCellRenderer();
|
private static final int TOP_DOMAINS_COUNT = 10;
|
||||||
|
|
||||||
static {
|
private final SwingWorkerSequentialRunner loader = new SwingWorkerSequentialRunner();
|
||||||
RIGHT_ALIGNED_RENDERER.setHorizontalAlignment(JLabel.RIGHT);
|
private final DataResultJTable<TopProgramsResult> topProgramsTable;
|
||||||
}
|
private final DataResultJTable<TopDomainsResult> recentDomainsTable;
|
||||||
|
private final List<DataFetchComponents<DataSource, ?>> dataFetchComponents;
|
||||||
|
|
||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
|
|
||||||
@ -63,8 +72,61 @@ public class DataSourceSummaryUserActivityPanel extends javax.swing.JPanel {
|
|||||||
* Creates new form DataSourceUserActivityPanel
|
* Creates new form DataSourceUserActivityPanel
|
||||||
*/
|
*/
|
||||||
public DataSourceSummaryUserActivityPanel() {
|
public DataSourceSummaryUserActivityPanel() {
|
||||||
|
this(new DataSourceTopProgramsSummary(), new DataSourceTopDomainsSummary());
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataSourceSummaryUserActivityPanel(DataSourceTopProgramsSummary topProgramsData, DataSourceTopDomainsSummary topDomainsData) {
|
||||||
|
// set up recent programs table
|
||||||
|
this.topProgramsTable = new DataResultJTable<>(new DefaultPojoListTableDataModel<>(Arrays.asList(
|
||||||
|
new DefaultColumnModel<TopProgramsResult>(
|
||||||
|
(prog) -> new DefaultCellModel(prog.getProgramName())
|
||||||
|
.setTooltip(prog.getProgramPath()),
|
||||||
|
Bundle.DataSourceSummaryUserActivityPanel_TopProgramsTableModel_name_header())
|
||||||
|
.setWidth(250),
|
||||||
|
new DefaultColumnModel<TopProgramsResult>(
|
||||||
|
Bundle.DataSourceSummaryUserActivityPanel_TopProgramsTableModel_folder_header(),
|
||||||
|
(prog) -> topProgramsData.getShortFolderName(prog.getProgramPath(), prog.getProgramName()))
|
||||||
|
.setWidth(150),
|
||||||
|
new DefaultColumnModel<TopProgramsResult>(
|
||||||
|
Bundle.DataSourceSummaryUserActivityPanel_TopProgramsTableModel_count_header(),
|
||||||
|
(prog) -> prog.getRunTimes() == null ? "" : Long.toString(prog.getRunTimes()))
|
||||||
|
.setWidth(80)
|
||||||
|
.setCellHorizontalAlignment(HorizontalAlign.RIGHT),
|
||||||
|
new DefaultColumnModel<TopProgramsResult>(
|
||||||
|
Bundle.DataSourceSummaryUserActivityPanel_TopProgramsTableModel_lastrun_header(),
|
||||||
|
(prog) -> prog.getLastRun() == null ? "" : DATETIME_FORMAT.format(prog.getLastRun()))
|
||||||
|
.setWidth(150)
|
||||||
|
.setCellHorizontalAlignment(HorizontalAlign.RIGHT)
|
||||||
|
)));
|
||||||
|
|
||||||
|
// set up recent domains table
|
||||||
|
recentDomainsTable = new DataResultJTable<>(new DefaultPojoListTableDataModel<>(Arrays.asList(
|
||||||
|
new DefaultColumnModel<TopDomainsResult>(
|
||||||
|
Bundle.DataSourceSummaryUserActivityPanel_TopDomainsTableModel_domain_header(),
|
||||||
|
(d) -> d.getDomain())
|
||||||
|
.setWidth(250),
|
||||||
|
new DefaultColumnModel<TopDomainsResult>(
|
||||||
|
Bundle.DataSourceSummaryUserActivityPanel_TopDomainsTableModel_url_header(),
|
||||||
|
(d) -> d.getUrl())
|
||||||
|
.setWidth(250),
|
||||||
|
new DefaultColumnModel<TopDomainsResult>(
|
||||||
|
Bundle.DataSourceSummaryUserActivityPanel_TopDomainsTableModel_lastAccess_header(),
|
||||||
|
(d) -> DATETIME_FORMAT.format(d.getLastVisit()))
|
||||||
|
.setWidth(150)
|
||||||
|
.setCellHorizontalAlignment(HorizontalAlign.RIGHT)
|
||||||
|
)));
|
||||||
|
|
||||||
|
// set up acquisition methods
|
||||||
|
dataFetchComponents = Arrays.asList(
|
||||||
|
new DataFetchComponents<DataSource, List<TopProgramsResult>>(
|
||||||
|
(dataSource) -> topProgramsData.getTopPrograms(dataSource, TOP_PROGS_COUNT),
|
||||||
|
topProgramsTable::setResult),
|
||||||
|
new DataFetchComponents<DataSource, List<TopDomainsResult>>(
|
||||||
|
(dataSource) -> topDomainsData.getRecentDomains(dataSource, TOP_DOMAINS_COUNT),
|
||||||
|
recentDomainsTable::setResult)
|
||||||
|
);
|
||||||
|
|
||||||
initComponents();
|
initComponents();
|
||||||
topProgramsTable.getTableHeader().setReorderingAllowed(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -81,170 +143,25 @@ public class DataSourceSummaryUserActivityPanel extends javax.swing.JPanel {
|
|||||||
*
|
*
|
||||||
* @param dataSource The datasource to use in this panel.
|
* @param dataSource The datasource to use in this panel.
|
||||||
*/
|
*/
|
||||||
public void setDataSource(DataSource dataSource) {
|
public void setDataSource(final DataSource dataSource) {
|
||||||
this.dataSource = dataSource;
|
this.dataSource = dataSource;
|
||||||
if (dataSource == null || !Case.isCaseOpen()) {
|
if (dataSource == null || !Case.isCaseOpen()) {
|
||||||
updateTopPrograms(new TopProgramsModel(null));
|
dataFetchComponents.forEach((item) -> item.getResultHandler()
|
||||||
|
.accept(DataLoadingResult.getLoaded(null)));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
updateTopPrograms(getTopProgramsModel(dataSource));
|
dataFetchComponents.forEach((item) -> item.getResultHandler()
|
||||||
|
.accept(DataLoadingResult.getLoading()));
|
||||||
|
|
||||||
|
List<DataFetchWorker<?, ?>> workers = dataFetchComponents
|
||||||
|
.stream()
|
||||||
|
.map((components) -> new DataFetchWorker<>(components, dataSource))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
loader.resetLoad(workers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the Top Programs Table in the gui.
|
|
||||||
*
|
|
||||||
* @param data The data in Object[][] form to be used by the
|
|
||||||
* DefaultTableModel.
|
|
||||||
*/
|
|
||||||
private void updateTopPrograms(TopProgramsModel model) {
|
|
||||||
topProgramsTable.setModel(model);
|
|
||||||
topProgramsTable.getColumnModel().getColumn(0).setPreferredWidth(250);
|
|
||||||
topProgramsTable.getColumnModel().getColumn(0).setCellRenderer(PATH_CELL_RENDERER);
|
|
||||||
topProgramsTable.getColumnModel().getColumn(1).setPreferredWidth(150);
|
|
||||||
topProgramsTable.getColumnModel().getColumn(2).setCellRenderer(RIGHT_ALIGNED_RENDERER);
|
|
||||||
topProgramsTable.getColumnModel().getColumn(2).setPreferredWidth(80);
|
|
||||||
topProgramsTable.getColumnModel().getColumn(3).setPreferredWidth(150);
|
|
||||||
topProgramsScrollPane.getVerticalScrollBar().setValue(0);
|
|
||||||
this.repaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The counts of top programs run.
|
|
||||||
*
|
|
||||||
* @param selectedDataSource The DataSource.
|
|
||||||
*
|
|
||||||
* @return The JTable data model of counts of program runs.
|
|
||||||
*/
|
|
||||||
private static TopProgramsModel getTopProgramsModel(DataSource selectedDataSource) {
|
|
||||||
List<TopProgramsResult> topProgramList
|
|
||||||
= DataSourceTopProgramsSummary.getTopPrograms(selectedDataSource, TOP_PROGS_COUNT);
|
|
||||||
|
|
||||||
if (topProgramList == null) {
|
|
||||||
return new TopProgramsModel(null);
|
|
||||||
} else {
|
|
||||||
return new TopProgramsModel(topProgramList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A POJO defining the values present in the name cell. Defines the name as
|
|
||||||
* well as the path for the tooltip.
|
|
||||||
*/
|
|
||||||
private static class ProgramNameCellValue {
|
|
||||||
|
|
||||||
private final String programName;
|
|
||||||
private final String programPath;
|
|
||||||
|
|
||||||
ProgramNameCellValue(String programName, String programPath) {
|
|
||||||
this.programName = programName;
|
|
||||||
this.programPath = programPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
// override so that the value in the cell reads as programName
|
|
||||||
return programName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The program name.
|
|
||||||
*/
|
|
||||||
String getProgramName() {
|
|
||||||
return programName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The path of the program.
|
|
||||||
*/
|
|
||||||
String getProgramPath() {
|
|
||||||
return programPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a cell renderer for the first cell rendering the name as the text
|
|
||||||
* and path as the tooltip.
|
|
||||||
*/
|
|
||||||
private static TableCellRenderer PATH_CELL_RENDERER = new DefaultTableCellRenderer() {
|
|
||||||
|
|
||||||
public Component getTableCellRendererComponent(
|
|
||||||
JTable table, Object value,
|
|
||||||
boolean isSelected, boolean hasFocus,
|
|
||||||
int row, int column) {
|
|
||||||
JLabel c = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
|
||||||
if (value instanceof ProgramNameCellValue) {
|
|
||||||
ProgramNameCellValue cellValue = (ProgramNameCellValue) value;
|
|
||||||
c.setToolTipText(cellValue.getProgramPath());
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines the table model for a JTable of the programs. Accepts a list of
|
|
||||||
* TopProgramsResult objects as rows data source.
|
|
||||||
*/
|
|
||||||
private static class TopProgramsModel extends AbstractTableModel {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
// column headers for artifact counts table
|
|
||||||
private static final String[] TOP_PROGS_COLUMN_HEADERS = new String[]{
|
|
||||||
Bundle.DataSourceSummaryUserActivityPanel_TopProgramsTableModel_name_header(),
|
|
||||||
Bundle.DataSourceSummaryUserActivityPanel_TopProgramsTableModel_folder_header(),
|
|
||||||
Bundle.DataSourceSummaryUserActivityPanel_TopProgramsTableModel_count_header(),
|
|
||||||
Bundle.DataSourceSummaryUserActivityPanel_TopProgramsTableModel_lastrun_header()
|
|
||||||
};
|
|
||||||
|
|
||||||
private final List<TopProgramsResult> programResults;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main constructor.
|
|
||||||
*
|
|
||||||
* @param programResults The results to display.
|
|
||||||
*/
|
|
||||||
TopProgramsModel(List<TopProgramsResult> programResults) {
|
|
||||||
this.programResults = programResults == null ? new ArrayList<>() : Collections.unmodifiableList(programResults);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getColumnName(int column) {
|
|
||||||
return column < 0 || column >= TOP_PROGS_COLUMN_HEADERS.length ? null : TOP_PROGS_COLUMN_HEADERS[column];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getRowCount() {
|
|
||||||
return programResults.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getColumnCount() {
|
|
||||||
return TOP_PROGS_COLUMN_HEADERS.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
|
||||||
if (rowIndex < 0 || rowIndex >= programResults.size()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
TopProgramsResult result = programResults.get(rowIndex);
|
|
||||||
switch (columnIndex) {
|
|
||||||
case 0:
|
|
||||||
return new ProgramNameCellValue(result.getProgramName(), result.getProgramPath());
|
|
||||||
case 1:
|
|
||||||
return DataSourceTopProgramsSummary.getShortFolderName(result.getProgramPath(), result.getProgramName());
|
|
||||||
case 2:
|
|
||||||
return result.getRunTimes();
|
|
||||||
case 3:
|
|
||||||
return result.getLastRun() == null ? null : DATETIME_FORMAT.format(result.getLastRun());
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called from within the constructor to initialize the form.
|
* 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
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
@ -254,40 +171,57 @@ public class DataSourceSummaryUserActivityPanel extends javax.swing.JPanel {
|
|||||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
private void initComponents() {
|
private void initComponents() {
|
||||||
|
|
||||||
|
javax.swing.JScrollPane contentScrollPane = new javax.swing.JScrollPane();
|
||||||
|
javax.swing.JPanel contentPanel = new javax.swing.JPanel();
|
||||||
javax.swing.JLabel programsRunLabel = new javax.swing.JLabel();
|
javax.swing.JLabel programsRunLabel = new javax.swing.JLabel();
|
||||||
topProgramsScrollPane = new javax.swing.JScrollPane();
|
javax.swing.Box.Filler filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2));
|
||||||
topProgramsTable = new javax.swing.JTable();
|
javax.swing.JPanel topProgramsTablePanel = topProgramsTable;
|
||||||
|
javax.swing.Box.Filler filler3 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20));
|
||||||
|
javax.swing.JLabel recentDomainsLabel = new javax.swing.JLabel();
|
||||||
|
javax.swing.Box.Filler filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2));
|
||||||
|
javax.swing.JPanel recentDomainsTablePanel = recentDomainsTable;
|
||||||
|
|
||||||
|
setMaximumSize(null);
|
||||||
|
setLayout(new java.awt.BorderLayout());
|
||||||
|
|
||||||
|
contentScrollPane.setMaximumSize(null);
|
||||||
|
contentScrollPane.setMinimumSize(null);
|
||||||
|
|
||||||
|
contentPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||||
|
contentPanel.setMaximumSize(new java.awt.Dimension(720, 450));
|
||||||
|
contentPanel.setMinimumSize(new java.awt.Dimension(720, 450));
|
||||||
|
contentPanel.setLayout(new javax.swing.BoxLayout(contentPanel, javax.swing.BoxLayout.PAGE_AXIS));
|
||||||
|
|
||||||
|
programsRunLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
|
||||||
org.openide.awt.Mnemonics.setLocalizedText(programsRunLabel, org.openide.util.NbBundle.getMessage(DataSourceSummaryUserActivityPanel.class, "DataSourceSummaryUserActivityPanel.programsRunLabel.text")); // NOI18N
|
org.openide.awt.Mnemonics.setLocalizedText(programsRunLabel, org.openide.util.NbBundle.getMessage(DataSourceSummaryUserActivityPanel.class, "DataSourceSummaryUserActivityPanel.programsRunLabel.text")); // NOI18N
|
||||||
|
programsRunLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||||
|
contentPanel.add(programsRunLabel);
|
||||||
|
contentPanel.add(filler1);
|
||||||
|
|
||||||
topProgramsScrollPane.setPreferredSize(new java.awt.Dimension(750, 187));
|
topProgramsTablePanel.setAlignmentX(0.0F);
|
||||||
topProgramsScrollPane.setViewportView(topProgramsTable);
|
topProgramsTablePanel.setMaximumSize(new java.awt.Dimension(700, 187));
|
||||||
|
topProgramsTablePanel.setMinimumSize(new java.awt.Dimension(700, 187));
|
||||||
|
topProgramsTablePanel.setPreferredSize(new java.awt.Dimension(700, 187));
|
||||||
|
contentPanel.add(topProgramsTablePanel);
|
||||||
|
contentPanel.add(filler3);
|
||||||
|
|
||||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
recentDomainsLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
|
||||||
this.setLayout(layout);
|
org.openide.awt.Mnemonics.setLocalizedText(recentDomainsLabel, org.openide.util.NbBundle.getMessage(DataSourceSummaryUserActivityPanel.class, "DataSourceSummaryUserActivityPanel.recentDomainsLabel.text")); // NOI18N
|
||||||
layout.setHorizontalGroup(
|
contentPanel.add(recentDomainsLabel);
|
||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
contentPanel.add(filler2);
|
||||||
.addGroup(layout.createSequentialGroup()
|
|
||||||
.addContainerGap()
|
recentDomainsTablePanel.setAlignmentX(0.0F);
|
||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
recentDomainsTablePanel.setMaximumSize(new java.awt.Dimension(700, 187));
|
||||||
.addComponent(programsRunLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE)
|
recentDomainsTablePanel.setMinimumSize(new java.awt.Dimension(700, 187));
|
||||||
.addComponent(topProgramsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 460, javax.swing.GroupLayout.PREFERRED_SIZE))
|
recentDomainsTablePanel.setPreferredSize(new java.awt.Dimension(700, 187));
|
||||||
.addContainerGap(128, Short.MAX_VALUE))
|
contentPanel.add(recentDomainsTablePanel);
|
||||||
);
|
|
||||||
layout.setVerticalGroup(
|
contentScrollPane.setViewportView(contentPanel);
|
||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
||||||
.addGroup(layout.createSequentialGroup()
|
add(contentScrollPane, java.awt.BorderLayout.CENTER);
|
||||||
.addContainerGap()
|
|
||||||
.addComponent(programsRunLabel)
|
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
|
||||||
.addComponent(topProgramsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
|
||||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
|
||||||
);
|
|
||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private javax.swing.JScrollPane topProgramsScrollPane;
|
|
||||||
private javax.swing.JTable topProgramsTable;
|
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
DataResultJTable_errorMessage_defaultText=There was an error loading results.
|
||||||
|
DataResultJTable_loadingMessage_defaultText=Loading results...
|
@ -121,24 +121,35 @@ public class DataFetchWorker<A, R> extends SwingWorker<R, Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void done() {
|
protected void done() {
|
||||||
|
// if cancelled, simply return
|
||||||
|
if (Thread.interrupted() || isCancelled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
R result = null;
|
R result = null;
|
||||||
try {
|
try {
|
||||||
result = get();
|
result = get();
|
||||||
} catch (InterruptedException ignored) {
|
} catch (InterruptedException ignored) {
|
||||||
// if cancelled, set not loaded andt return
|
// if cancelled, simply return
|
||||||
resultHandler.accept(DataLoadingResult.getNotLoaded());
|
|
||||||
return;
|
return;
|
||||||
} catch (ExecutionException ex) {
|
} catch (ExecutionException ex) {
|
||||||
logger.log(Level.WARNING, "There was an error while fetching results.", ex);
|
|
||||||
Throwable inner = ex.getCause();
|
Throwable inner = ex.getCause();
|
||||||
|
// if cancelled during operation, simply return
|
||||||
|
if (inner != null && inner instanceof InterruptedException) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise, there is an error to log
|
||||||
|
logger.log(Level.WARNING, "There was an error while fetching results.", ex);
|
||||||
|
|
||||||
if (inner != null && inner instanceof DataProcessorException) {
|
if (inner != null && inner instanceof DataProcessorException) {
|
||||||
resultHandler.accept(DataLoadingResult.getLoadError((DataProcessorException) inner));
|
resultHandler.accept(DataLoadingResult.getLoadError((DataProcessorException) inner));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if cancelled, simply return
|
||||||
if (Thread.interrupted() || isCancelled()) {
|
if (Thread.interrupted() || isCancelled()) {
|
||||||
resultHandler.accept(DataLoadingResult.getNotLoaded());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ package org.sleuthkit.autopsy.guiutils.internal;
|
|||||||
/**
|
/**
|
||||||
* The intermediate or end result of a loading process.
|
* The intermediate or end result of a loading process.
|
||||||
*/
|
*/
|
||||||
class DataLoadingResult<R> {
|
public class DataLoadingResult<R> {
|
||||||
|
|
||||||
// The state of loading in the result.
|
// The state of loading in the result.
|
||||||
public enum ProcessorState {
|
public enum ProcessorState {
|
||||||
|
@ -243,7 +243,7 @@ public class DefaultPojoListTableDataModel<T> extends AbstractTableModel impleme
|
|||||||
TableColumn col = new TableColumn(i);
|
TableColumn col = new TableColumn(i);
|
||||||
ColumnModel<T> model = columns.get(i);
|
ColumnModel<T> model = columns.get(i);
|
||||||
if (model.getWidth() != null && model.getWidth() >= 0) {
|
if (model.getWidth() != null && model.getWidth() >= 0) {
|
||||||
col.setWidth(model.getWidth());
|
col.setPreferredWidth(model.getWidth());
|
||||||
}
|
}
|
||||||
|
|
||||||
col.setHeaderValue(model.getTitle());
|
col.setHeaderValue(model.getTitle());
|
||||||
@ -278,11 +278,15 @@ public class DefaultPojoListTableDataModel<T> extends AbstractTableModel impleme
|
|||||||
String text = cellModel.getText();
|
String text = cellModel.getText();
|
||||||
if (StringUtils.isNotBlank(text)) {
|
if (StringUtils.isNotBlank(text)) {
|
||||||
defaultCell.setText(text);
|
defaultCell.setText(text);
|
||||||
|
} else {
|
||||||
|
defaultCell.setText(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
String tooltip = cellModel.getTooltip();
|
String tooltip = cellModel.getTooltip();
|
||||||
if (StringUtils.isNotBlank(tooltip)) {
|
if (StringUtils.isNotBlank(tooltip)) {
|
||||||
defaultCell.setToolTipText(tooltip);
|
defaultCell.setToolTipText(tooltip);
|
||||||
|
} else {
|
||||||
|
defaultCell.setToolTipText(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (columnModel.getCellHorizontalAlignment() != null) {
|
if (columnModel.getCellHorizontalAlignment() != null) {
|
||||||
@ -297,6 +301,8 @@ public class DefaultPojoListTableDataModel<T> extends AbstractTableModel impleme
|
|||||||
defaultCell.setHorizontalAlignment(JLabel.RIGHT);
|
defaultCell.setHorizontalAlignment(JLabel.RIGHT);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
defaultCell.setHorizontalAlignment(JLabel.LEFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
return defaultCell;
|
return defaultCell;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user