Merge branch 'develop' of https://github.com/sleuthkit/autopsy into 3757_views_by_datasource

This commit is contained in:
Raman 2018-04-27 11:09:16 -04:00
commit 56ba0edeec
99 changed files with 4442 additions and 2754 deletions

View File

@ -86,7 +86,9 @@
<mkdir dir="${basedir}/test/qa-functional/data"/>
<get src="https://drive.google.com/uc?id=0BxdBkzm5VKGNT0dGY0dqcHVsU3M" dest="${test-input}/filter_test1.img" skipexisting="true"/>
<get src="https://drive.google.com/uc?id=1bghoSm7z7nhmGIxlllyY1MMlbLntxm7n" dest="${test-input}/local_files_test.zip" skipexisting="true"/>
</target>
<get src="https://drive.google.com/uc?id=1dLYGctuvRQMmnzfXPppTM_9gB49eLc_g" dest="${test-input}/embedded.vhd" skipexisting="true"/>
</target>
<target name="get-deps" depends="init-ivy,getTSKJars,get-thirdparty-dependencies,get-InternalPythonModules, download-binlist, getTestDataFiles">
<mkdir dir="${ext.dir}"/>
<copy file="${thirdparty.dir}/LICENSE-2.0.txt" todir="${ext.dir}" />

View File

@ -327,6 +327,7 @@
<package>org.sleuthkit.autopsy.events</package>
<package>org.sleuthkit.autopsy.filesearch</package>
<package>org.sleuthkit.autopsy.guiutils</package>
<package>org.sleuthkit.autopsy.healthmonitor</package>
<package>org.sleuthkit.autopsy.ingest</package>
<package>org.sleuthkit.autopsy.keywordsearchservice</package>
<package>org.sleuthkit.autopsy.menuactions</package>

View File

@ -115,19 +115,19 @@ final class MultiUserNode extends AbstractNode {
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(),
sheetSet.put(new NodeProperty<>(Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(),
caseName));
ss.put(new NodeProperty<>(Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(),
sheetSet.put(new NodeProperty<>(Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(),
caseCreatedDate));
ss.put(new NodeProperty<>(Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(),
sheetSet.put(new NodeProperty<>(Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(),
caseMetadataFilePath));
return s;
return sheet;
}
@Override

View File

@ -68,7 +68,17 @@ public class IngestModuleFactory extends IngestModuleFactoryAdapter {
@Override
public FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings settings) {
return new IngestModule((IngestSettings) settings);
if (settings instanceof IngestSettings) {
return new IngestModule((IngestSettings) settings);
}
/*
* Compatibility check for older versions.
*/
if (settings instanceof NoIngestModuleIngestJobSettings) {
return new IngestModule(new IngestSettings());
}
throw new IllegalArgumentException("Expected settings argument to be an instance of IngestSettings");
}
@Override

View File

@ -74,11 +74,11 @@ final class AccountDeviceInstanceNode extends AbstractNode {
@Override
@NbBundle.Messages(value = {"AccountNode.device=Device", "AccountNode.accountName=Account", "AccountNode.accountType=Type", "AccountNode.messageCount=Msgs"})
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set properties = s.get(Sheet.PROPERTIES);
Sheet sheet = super.createSheet();
Sheet.Set properties = sheet.get(Sheet.PROPERTIES);
if (properties == null) {
properties = Sheet.createPropertiesSet();
s.put(properties);
sheet.put(properties);
}
properties.put(new NodeProperty<>("type",
Bundle.AccountNode_accountType(),
@ -92,7 +92,7 @@ final class AccountDeviceInstanceNode extends AbstractNode {
Bundle.AccountNode_device(),
"device",
accountDeviceInstanceKey.getDataSourceName())); // NON-NLS
return s;
return sheet;
}
@Override

View File

@ -56,14 +56,14 @@ final class RelationshipNode extends BlackboardArtifactNode {
@Override
protected Sheet createSheet() {
Sheet s = new Sheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = new Sheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>("Type", "Type", "Type", getDisplayName()));
sheetSet.put(new NodeProperty<>("Type", "Type", "Type", getDisplayName()));
final BlackboardArtifact artifact = getArtifact();
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(getArtifact().getArtifactTypeID());
@ -71,42 +71,42 @@ final class RelationshipNode extends BlackboardArtifactNode {
//Consider refactoring this to reduce boilerplate
switch (fromID) {
case TSK_EMAIL_MSG:
ss.put(new NodeProperty<>("From", "From", "From",
sheetSet.put(new NodeProperty<>("From", "From", "From",
StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_FROM), " \t\n;")));
ss.put(new NodeProperty<>("To", "To", "To",
sheetSet.put(new NodeProperty<>("To", "To", "To",
StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_TO), " \t\n;")));
ss.put(new NodeProperty<>("Date", "Date", "Date",
sheetSet.put(new NodeProperty<>("Date", "Date", "Date",
getAttributeDisplayString(artifact, TSK_DATETIME_SENT)));
ss.put(new NodeProperty<>("Subject", "Subject", "Subject",
sheetSet.put(new NodeProperty<>("Subject", "Subject", "Subject",
getAttributeDisplayString(artifact, TSK_SUBJECT)));
try {
ss.put(new NodeProperty<>("Attms", "Attms", "Attms", artifact.getChildrenCount()));
sheetSet.put(new NodeProperty<>("Attms", "Attms", "Attms", artifact.getChildrenCount()));
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Error loading attachment count for " + artifact, ex);
}
break;
case TSK_MESSAGE:
ss.put(new NodeProperty<>("From", "From", "From",
sheetSet.put(new NodeProperty<>("From", "From", "From",
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM)));
ss.put(new NodeProperty<>("To", "To", "To",
sheetSet.put(new NodeProperty<>("To", "To", "To",
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO)));
ss.put(new NodeProperty<>("Date", "Date", "Date",
sheetSet.put(new NodeProperty<>("Date", "Date", "Date",
getAttributeDisplayString(artifact, TSK_DATETIME)));
ss.put(new NodeProperty<>("Subject", "Subject", "Subject",
sheetSet.put(new NodeProperty<>("Subject", "Subject", "Subject",
getAttributeDisplayString(artifact, TSK_SUBJECT)));
try {
ss.put(new NodeProperty<>("Attms", "Attms", "Attms", artifact.getChildrenCount()));
sheetSet.put(new NodeProperty<>("Attms", "Attms", "Attms", artifact.getChildrenCount()));
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Error loading attachment count for " + artifact, ex);
}
break;
case TSK_CALLLOG:
ss.put(new NodeProperty<>("From", "From", "From",
sheetSet.put(new NodeProperty<>("From", "From", "From",
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM)));
ss.put(new NodeProperty<>("To", "To", "To",
sheetSet.put(new NodeProperty<>("To", "To", "To",
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO)));
ss.put(new NodeProperty<>("Date", "Date", "Date",
sheetSet.put(new NodeProperty<>("Date", "Date", "Date",
getAttributeDisplayString(artifact, TSK_DATETIME_START)));
break;
default:
@ -114,9 +114,9 @@ final class RelationshipNode extends BlackboardArtifactNode {
}
}
addTagProperty(ss);
addTagProperty(sheetSet);
return s;
return sheet;
}
/**

View File

@ -208,11 +208,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
applyLayout(fastOrganicLayout);
}
/**
*
* @param layoutButton the value of layoutButton
* @param layout the value of layout
*/
@Override
public Lookup getLookup() {
return proxyLookup;

View File

@ -716,20 +716,20 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
@Override
protected Sheet createSheet() {
Sheet s = new Sheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = new Sheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
AbstractFile file = getContent();
ss.put(new NodeProperty<>("Name", "Name", "Name", file.getName()));
ss.put(new NodeProperty<>("Size", "Size", "Size", file.getSize()));
ss.put(new NodeProperty<>("Mime Type", "Mime Type", "Mime Type", StringUtils.defaultString(file.getMIMEType())));
ss.put(new NodeProperty<>("Known", "Known", "Known", file.getKnown().getName()));
sheetSet.put(new NodeProperty<>("Name", "Name", "Name", file.getName()));
sheetSet.put(new NodeProperty<>("Size", "Size", "Size", file.getSize()));
sheetSet.put(new NodeProperty<>("Mime Type", "Mime Type", "Mime Type", StringUtils.defaultString(file.getMIMEType())));
sheetSet.put(new NodeProperty<>("Known", "Known", "Known", file.getKnown().getName()));
addTagProperty(ss);
return s;
addTagProperty(sheetSet);
return sheet;
}
}
}

View File

@ -11,7 +11,7 @@
</NonVisualComponents>
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[610, 52]"/>
<Dimension value="[100, 52]"/>
</Property>
</Properties>
<AuxValues>
@ -41,7 +41,8 @@
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane2">
<Properties>
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
<Property name="horizontalScrollBarPolicy" type="int" value="32"/>
<Property name="verticalScrollBarPolicy" type="int" value="22"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[610, 52]"/>
</Property>

View File

@ -59,9 +59,10 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer {
jScrollPane2 = new javax.swing.JScrollPane();
jTextPane1 = new javax.swing.JTextPane();
setPreferredSize(new java.awt.Dimension(610, 52));
setPreferredSize(new java.awt.Dimension(100, 52));
jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
jScrollPane2.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
jScrollPane2.setPreferredSize(new java.awt.Dimension(610, 52));
jTextPane1.setEditable(false);

View File

@ -455,7 +455,8 @@ public final class CoordinationService {
CASES("cases"),
MANIFESTS("manifests"),
CONFIG("config"),
CENTRAL_REPO("centralRepository");
CENTRAL_REPO("centralRepository"),
HEALTH_MONITOR("healthMonitor");
private final String displayName;

View File

@ -216,6 +216,7 @@ public class Installer extends ModuleInstall {
packageInstallers.add(org.sleuthkit.autopsy.datamodel.Installer.getDefault());
packageInstallers.add(org.sleuthkit.autopsy.ingest.Installer.getDefault());
packageInstallers.add(org.sleuthkit.autopsy.centralrepository.eventlisteners.Installer.getDefault());
packageInstallers.add(org.sleuthkit.autopsy.healthmonitor.Installer.getDefault());
}
/**

View File

@ -213,7 +213,7 @@
</file>-->
<file name="org-sleuthkit-autopsy-report-ReportWizardAction-separatorAfter.instance">
<attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
<attr name="position" intvalue="104"/>
<attr name="position" intvalue="199"/>
</file>
<!--<file name="Separator1.instance_hidden"/>
<file name="Separator3.instance_hidden"/>-->

View File

@ -27,7 +27,7 @@
</NonVisualComponents>
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[622, 58]"/>
<Dimension value="[100, 58]"/>
</Property>
</Properties>
<AuxValues>
@ -45,201 +45,214 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jPanel1" pref="622" max="32767" attributes="0"/>
<Component id="jScrollPane1" max="32767" attributes="0"/>
<Component id="resultsTableScrollPane" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jPanel1" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="jScrollPane1" min="-2" pref="24" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="resultsTableScrollPane" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel1">
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[620, 58]"/>
</Property>
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
<Property name="verticalScrollBarPolicy" type="int" value="21"/>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="pageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="currentPageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="ofLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="totalPageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="41" max="-2" attributes="0"/>
<Component id="pageLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="prevPageButton" min="-2" pref="23" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="nextPageButton" min="-2" pref="23" max="-2" attributes="0"/>
<EmptySpace pref="334" max="32767" attributes="0"/>
</Group>
<Component id="resultsTableScrollPane" alignment="1" max="32767" attributes="0"/>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace pref="280" max="32767" attributes="0"/>
<Component id="artifactLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="84" max="32767" attributes="0"/>
</Group>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
<Component id="pageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="currentPageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="ofLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="totalPageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="nextPageButton" alignment="0" min="-2" pref="23" max="-2" attributes="0"/>
<Component id="prevPageButton" alignment="0" min="-2" pref="23" max="-2" attributes="0"/>
<Component id="pageLabel2" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="resultsTableScrollPane" pref="29" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
</Group>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="artifactLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="401" max="32767" attributes="0"/>
</Group>
</Group>
</Group>
</DimensionLayout>
</Layout>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JLabel" name="totalPageLabel">
<Container class="javax.swing.JPanel" name="jPanel1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerArtifact.totalPageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="ofLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerArtifact.ofLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="currentPageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerArtifact.currentPageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
<Dimension value="[620, 58]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="pageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerArtifact.pageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</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/corecomponents/Bundle.properties" key="DataContentViewerArtifact.nextPageButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="disabledIcon" 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>
<Property name="rolloverIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="nextPageButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="pageLabel2">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerArtifact.pageLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[29, 14]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[29, 14]"/>
</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/corecomponents/Bundle.properties" key="DataContentViewerArtifact.prevPageButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="disabledIcon" 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>
<Property name="rolloverIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="prevPageButtonActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JScrollPane" name="resultsTableScrollPane">
<Properties>
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[620, 34]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="pageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="currentPageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="ofLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="totalPageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="41" max="-2" attributes="0"/>
<Component id="pageLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="prevPageButton" min="-2" pref="23" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="nextPageButton" min="-2" pref="23" max="-2" attributes="0"/>
<EmptySpace pref="383" max="32767" attributes="0"/>
</Group>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace pref="280" max="32767" attributes="0"/>
<Component id="artifactLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="84" max="32767" attributes="0"/>
</Group>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
<Component id="pageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="currentPageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="ofLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="totalPageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="nextPageButton" alignment="0" min="-2" pref="23" max="-2" attributes="0"/>
<Component id="prevPageButton" alignment="0" min="-2" pref="23" max="-2" attributes="0"/>
<Component id="pageLabel2" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="35" max="32767" attributes="0"/>
</Group>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="artifactLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="58" max="32767" attributes="0"/>
</Group>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="totalPageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerArtifact.totalPageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="ofLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerArtifact.ofLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="currentPageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerArtifact.currentPageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="pageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerArtifact.pageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</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/corecomponents/Bundle.properties" key="DataContentViewerArtifact.nextPageButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="disabledIcon" 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>
<Property name="rolloverIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="nextPageButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="pageLabel2">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerArtifact.pageLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[29, 14]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[29, 14]"/>
</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/corecomponents/Bundle.properties" key="DataContentViewerArtifact.prevPageButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="disabledIcon" 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>
<Property name="rolloverIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="prevPageButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="artifactLabel">
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="artifactLabel">
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JScrollPane" name="resultsTableScrollPane">
<Properties>
<Property name="horizontalScrollBarPolicy" type="int" value="32"/>
<Property name="verticalScrollBarPolicy" type="int" value="22"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[620, 34]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
</Container>
</SubComponents>
</Form>

View File

@ -200,6 +200,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
rightClickMenu = new javax.swing.JPopupMenu();
copyMenuItem = new javax.swing.JMenuItem();
selectAllMenuItem = new javax.swing.JMenuItem();
jScrollPane1 = new javax.swing.JScrollPane();
jPanel1 = new javax.swing.JPanel();
totalPageLabel = new javax.swing.JLabel();
ofLabel = new javax.swing.JLabel();
@ -208,8 +209,8 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
nextPageButton = new javax.swing.JButton();
pageLabel2 = new javax.swing.JLabel();
prevPageButton = new javax.swing.JButton();
resultsTableScrollPane = new javax.swing.JScrollPane();
artifactLabel = new javax.swing.JLabel();
resultsTableScrollPane = new javax.swing.JScrollPane();
copyMenuItem.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.copyMenuItem.text")); // NOI18N
rightClickMenu.add(copyMenuItem);
@ -217,7 +218,10 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.selectAllMenuItem.text")); // NOI18N
rightClickMenu.add(selectAllMenuItem);
setPreferredSize(new java.awt.Dimension(622, 58));
setPreferredSize(new java.awt.Dimension(100, 58));
jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
jScrollPane1.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
jPanel1.setPreferredSize(new java.awt.Dimension(620, 58));
@ -264,9 +268,6 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
}
});
resultsTableScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
resultsTableScrollPane.setPreferredSize(new java.awt.Dimension(620, 34));
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
@ -286,8 +287,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
.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(334, Short.MAX_VALUE))
.addComponent(resultsTableScrollPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap(383, Short.MAX_VALUE))
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addContainerGap(280, Short.MAX_VALUE)
@ -306,24 +306,32 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
.addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(pageLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(resultsTableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 29, Short.MAX_VALUE)
.addGap(0, 0, 0))
.addContainerGap(35, Short.MAX_VALUE))
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(artifactLabel)
.addGap(0, 401, Short.MAX_VALUE)))
.addGap(0, 58, Short.MAX_VALUE)))
);
jScrollPane1.setViewportView(jPanel1);
resultsTableScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
resultsTableScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
resultsTableScrollPane.setPreferredSize(new java.awt.Dimension(620, 34));
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 622, Short.MAX_VALUE)
.addComponent(jScrollPane1)
.addComponent(resultsTableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(resultsTableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
@ -346,6 +354,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
private javax.swing.JMenuItem copyMenuItem;
private javax.swing.JLabel currentPageLabel;
private javax.swing.JPanel jPanel1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JButton nextPageButton;
private javax.swing.JLabel ofLabel;
private javax.swing.JLabel pageLabel;

View File

@ -27,7 +27,7 @@
</NonVisualComponents>
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[610, 58]"/>
<Dimension value="[100, 58]"/>
</Property>
</Properties>
<AuxValues>
@ -45,261 +45,253 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="hexViewerPanel" pref="701" max="32767" attributes="0"/>
<Component id="jScrollPane1" alignment="0" pref="0" max="32767" attributes="0"/>
<Component id="jScrollPane2" pref="100" max="32767" attributes="0"/>
<Component id="jScrollPane3" alignment="0" pref="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Component id="hexViewerPanel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="29" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="jScrollPane2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane3" pref="27" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="hexViewerPanel">
<Container class="javax.swing.JScrollPane" name="jScrollPane3">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[610, 23]"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="pageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="currentPageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="ofLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="totalPageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="50" max="-2" attributes="0"/>
<Component id="pageLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="prevPageButton" min="-2" pref="23" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="nextPageButton" min="-2" pref="23" max="-2" attributes="0"/>
<EmptySpace type="separate" min="-2" max="-2" attributes="0"/>
<Component id="goToPageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="goToPageTextField" min="-2" pref="79" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="goToOffsetLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="goToOffsetTextField" min="-2" pref="79" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="pageLabel" min="-2" max="-2" attributes="0"/>
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
<Component id="currentPageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="ofLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="totalPageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="pageLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="nextPageButton" alignment="0" min="-2" pref="23" max="-2" attributes="0"/>
<Component id="prevPageButton" alignment="0" min="-2" pref="23" max="-2" attributes="0"/>
<Component id="goToPageLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="goToPageTextField" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="goToOffsetLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="goToOffsetTextField" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="totalPageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerHex.totalPageLabel.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="ofLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerHex.ofLabel.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="currentPageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerHex.currentPageLabel.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="pageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerHex.pageLabel.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[33, 14]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[33, 14]"/>
</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/corecomponents/Bundle.properties" key="DataContentViewerHex.prevPageButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="disabledIcon" 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>
<Property name="rolloverIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png"/>
</Property>
</Properties>
<Events>
<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/corecomponents/Bundle.properties" key="DataContentViewerHex.nextPageButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="disabledIcon" 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>
<Property name="rolloverIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="nextPageButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="pageLabel2">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerHex.pageLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[29, 14]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[29, 14]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="goToPageTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerHex.goToPageTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="goToPageTextFieldActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="goToPageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerHex.goToPageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="goToOffsetLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerHex.goToOffsetLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="goToOffsetTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerHex.goToOffsetTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="goToOffsetTextFieldActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<Properties>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="ff" green="ff" red="ff" type="rgb"/>
</Property>
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[610, 402]"/>
<Dimension value="[300, 33]"/>
</Property>
</Properties>
<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.JTextPane" name="outputViewPane">
<Component class="javax.swing.JTextArea" name="outputTextArea">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Courier New" size="11" style="0"/>
</Property>
<Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
<Color id="Default Cursor"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[600, 20]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[700, 400]"/>
</Property>
<Property name="tabSize" type="int" value="0"/>
<Property name="inheritsPopupMenu" type="boolean" value="true"/>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new JTextPane(){&#xd; public boolean getScrollableTracksViewportWidth() {&#xd; return (getSize().width &lt; 400);&#xd; }};"/>
<AuxValue name="JavaCodeGenerator_CreateCodePost" type="java.lang.String" value="this.outputViewPane.setBackground(new java.awt.Color(255, 255, 255)); // to make sure the background color is white&#xd;&#xa;this.outputViewPane.requestFocusInWindow();&#xd;&#xa;this.outputViewPane.setCursor(Cursor.getDefaultCursor());&#xd;&#xa;"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JScrollPane" name="jScrollPane2">
<Properties>
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
<Property name="verticalScrollBarPolicy" type="int" value="21"/>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="hexViewerPanel">
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="pageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="currentPageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="ofLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="totalPageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="50" max="-2" attributes="0"/>
<Component id="pageLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="prevPageButton" min="-2" pref="23" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="nextPageButton" min="-2" pref="23" max="-2" attributes="0"/>
<EmptySpace type="separate" min="-2" max="-2" attributes="0"/>
<Component id="goToPageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="goToPageTextField" min="-2" pref="79" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="goToOffsetLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="goToOffsetTextField" min="-2" pref="79" max="-2" attributes="0"/>
<EmptySpace pref="32" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="pageLabel" min="-2" max="-2" attributes="0"/>
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
<Component id="currentPageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="ofLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="totalPageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="pageLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="nextPageButton" alignment="0" min="-2" pref="23" max="-2" attributes="0"/>
<Component id="prevPageButton" alignment="0" min="-2" pref="23" max="-2" attributes="0"/>
<Component id="goToPageLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="goToPageTextField" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="goToOffsetLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="goToOffsetTextField" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="totalPageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerHex.totalPageLabel.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="ofLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerHex.ofLabel.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="currentPageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerHex.currentPageLabel.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="pageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerHex.pageLabel.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[33, 14]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[33, 14]"/>
</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/corecomponents/Bundle.properties" key="DataContentViewerHex.prevPageButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="disabledIcon" 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>
<Property name="rolloverIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png"/>
</Property>
</Properties>
<Events>
<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/corecomponents/Bundle.properties" key="DataContentViewerHex.nextPageButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="disabledIcon" 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>
<Property name="rolloverIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="nextPageButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="pageLabel2">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerHex.pageLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[29, 14]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[29, 14]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="goToPageTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerHex.goToPageTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="goToPageTextFieldActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="goToPageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerHex.goToPageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="goToOffsetLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerHex.goToOffsetLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="goToOffsetTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerHex.goToOffsetTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="goToOffsetTextFieldActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -62,15 +62,15 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
}
private void customizeComponents() {
outputViewPane.setComponentPopupMenu(rightClickMenu);
outputTextArea.setComponentPopupMenu(rightClickMenu);
ActionListener actList = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JMenuItem jmi = (JMenuItem) e.getSource();
if (jmi.equals(copyMenuItem)) {
outputViewPane.copy();
outputTextArea.copy();
} else if (jmi.equals(selectAllMenuItem)) {
outputViewPane.selectAll();
outputTextArea.selectAll();
}
}
};
@ -90,6 +90,9 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
rightClickMenu = new javax.swing.JPopupMenu();
copyMenuItem = new javax.swing.JMenuItem();
selectAllMenuItem = new javax.swing.JMenuItem();
jScrollPane3 = new javax.swing.JScrollPane();
outputTextArea = new javax.swing.JTextArea();
jScrollPane2 = new javax.swing.JScrollPane();
hexViewerPanel = new javax.swing.JPanel();
totalPageLabel = new javax.swing.JLabel();
ofLabel = new javax.swing.JLabel();
@ -102,14 +105,6 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
goToPageLabel = new javax.swing.JLabel();
goToOffsetLabel = new javax.swing.JLabel();
goToOffsetTextField = new javax.swing.JTextField();
jScrollPane1 = new javax.swing.JScrollPane();
outputViewPane = new JTextPane(){
public boolean getScrollableTracksViewportWidth() {
return (getSize().width < 400);
}};
this.outputViewPane.setBackground(new java.awt.Color(255, 255, 255)); // to make sure the background color is white
this.outputViewPane.requestFocusInWindow();
this.outputViewPane.setCursor(Cursor.getDefaultCursor());
copyMenuItem.setText(org.openide.util.NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.copyMenuItem.text")); // NOI18N
rightClickMenu.add(copyMenuItem);
@ -117,9 +112,18 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.selectAllMenuItem.text")); // NOI18N
rightClickMenu.add(selectAllMenuItem);
setPreferredSize(new java.awt.Dimension(610, 58));
setPreferredSize(new java.awt.Dimension(100, 58));
hexViewerPanel.setPreferredSize(new java.awt.Dimension(610, 23));
jScrollPane3.setPreferredSize(new java.awt.Dimension(300, 33));
outputTextArea.setEditable(false);
outputTextArea.setFont(new java.awt.Font("Courier New", 0, 11)); // NOI18N
outputTextArea.setTabSize(0);
outputTextArea.setInheritsPopupMenu(true);
jScrollPane3.setViewportView(outputTextArea);
jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
jScrollPane2.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
totalPageLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.totalPageLabel.text_1")); // NOI18N
@ -210,7 +214,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
.addComponent(goToOffsetLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(goToOffsetTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap(32, Short.MAX_VALUE))
);
hexViewerPanelLayout.setVerticalGroup(
hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -231,31 +235,21 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
.addGap(0, 0, 0))
);
jScrollPane1.setBackground(new java.awt.Color(255, 255, 255));
jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
jScrollPane1.setPreferredSize(new java.awt.Dimension(610, 402));
outputViewPane.setEditable(false);
outputViewPane.setFont(new java.awt.Font("Courier New", 0, 11)); // NOI18N
outputViewPane.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
outputViewPane.setMinimumSize(new java.awt.Dimension(600, 20));
outputViewPane.setPreferredSize(new java.awt.Dimension(700, 400));
jScrollPane1.setViewportView(outputViewPane);
jScrollPane2.setViewportView(hexViewerPanel);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(hexViewerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 701, Short.MAX_VALUE)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 100, Short.MAX_VALUE)
.addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(hexViewerPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 29, Short.MAX_VALUE)
.addGap(0, 0, 0))
.addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 27, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
@ -305,16 +299,16 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
String userSelectedLine;
try {
// get the selected line. Extract the current hex offset location.
userSelectedLine = outputViewPane.getText().subSequence(
Utilities.getRowStart(outputViewPane, outputViewPane.getCaretPosition()),
Utilities.getRowEnd(outputViewPane, outputViewPane.getCaretPosition()))
userSelectedLine = outputTextArea.getText().subSequence(
Utilities.getRowStart(outputTextArea, outputTextArea.getCaretPosition()),
Utilities.getRowEnd(outputTextArea, outputTextArea.getCaretPosition()))
.toString();
// NOTE: This needs to change if the outputFormat of outputViewPane changes.
// NOTE: This needs to change if the outputFormat of outputTextArea changes.
String hexForUserSelectedLine = userSelectedLine.substring(0, userSelectedLine.indexOf(":"));
return Long.decode(hexForUserSelectedLine) + userInput;
} catch (BadLocationException | StringIndexOutOfBoundsException | NumberFormatException ex) {
// thrown in case the caret location is out of the range of the outputViewPane.
// thrown in case the caret location is out of the range of the outputTextArea.
return -1L;
}
}
@ -336,7 +330,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
if (offset >= 0) {
setDataViewByOffset(offset);
} else {
outputViewPane.setText(NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.setDataView.invalidOffset.negativeOffsetValue"));
outputTextArea.setText(NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.setDataView.invalidOffset.negativeOffsetValue"));
}
}//GEN-LAST:event_goToOffsetTextFieldActionPerformed
@ -348,10 +342,11 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
private javax.swing.JLabel goToPageLabel;
private javax.swing.JTextField goToPageTextField;
private javax.swing.JPanel hexViewerPanel;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JScrollPane jScrollPane3;
private javax.swing.JButton nextPageButton;
private javax.swing.JLabel ofLabel;
private javax.swing.JTextPane outputViewPane;
private javax.swing.JTextArea outputTextArea;
private javax.swing.JLabel pageLabel;
private javax.swing.JLabel pageLabel2;
private javax.swing.JButton prevPageButton;
@ -434,12 +429,12 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
// set the output view
if (errorText == null) {
int showLength = bytesRead < pageLength ? bytesRead : (int) pageLength;
outputViewPane.setText(DataConversion.byteArrayToHex(data, showLength, offset));
outputTextArea.setText(DataConversion.byteArrayToHex(data, showLength, offset));
} else {
outputViewPane.setText(errorText);
outputTextArea.setText(errorText);
}
outputViewPane.setCaretPosition(0);
outputTextArea.setCaretPosition(0);
this.setCursor(null);
}
@ -488,7 +483,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
this.dataSource = null;
currentPageLabel.setText("");
totalPageLabel.setText("");
outputViewPane.setText("");
outputTextArea.setText("");
setComponentsVisibility(false); // hides the components that not needed
}
@ -541,7 +536,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
if (evt.isPopupTrigger()) {
rightClickMenu.setLocation(evt.getLocationOnScreen());
rightClickMenu.setVisible(true);
copyMenuItem.setEnabled(outputViewPane.getSelectedText() != null);
copyMenuItem.setEnabled(outputTextArea.getSelectedText() != null);
} else {
rightClickMenu.setVisible(false);
}

View File

@ -29,6 +29,9 @@
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[5, 5]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[100, 144]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
@ -45,258 +48,258 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jPanel1" alignment="1" pref="728" max="32767" attributes="0"/>
<Component id="jScrollPane2" pref="0" max="32767" attributes="0"/>
<Component id="jScrollPane1" pref="100" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jPanel1" alignment="1" pref="58" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="jScrollPane2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="25" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel1">
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[640, 424]"/>
<Dimension value="[640, 402]"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="pageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" min="-2" max="-2" attributes="0"/>
<Component id="currentPageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="ofLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="totalPageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="50" max="-2" attributes="0"/>
<Component id="pageLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="prevPageButton" min="-2" pref="23" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="nextPageButton" min="-2" pref="23" max="-2" attributes="0"/>
<EmptySpace type="separate" min="-2" max="-2" attributes="0"/>
<Component id="goToPageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="goToPageTextField" min="-2" pref="79" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="33" max="-2" attributes="0"/>
<Component id="languageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="languageCombo" min="-2" pref="155" max="-2" attributes="0"/>
</Group>
<Component id="jScrollPane1" alignment="0" pref="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
<Component id="pageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="currentPageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="ofLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="totalPageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="pageLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="nextPageButton" alignment="0" min="-2" pref="23" max="-2" attributes="0"/>
<Component id="prevPageButton" alignment="0" min="-2" pref="23" max="-2" attributes="0"/>
<Component id="goToPageLabel" min="-2" max="-2" attributes="0"/>
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
<Component id="goToPageTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="languageCombo" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="languageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="29" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<Component class="javax.swing.JTextPane" name="outputViewPane">
<Properties>
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[640, 402]"/>
</Property>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextPane" name="outputViewPane">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Courier New" size="11" style="0"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[638, 400]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new JTextPane(){&#xd; public boolean getScrollableTracksViewportWidth() {&#xd; return (getSize().width &lt; 400);&#xd; }};"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="totalPageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.totalPageLabel.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="ofLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.ofLabel.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="currentPageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.currentPageLabel.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
<Property name="editable" type="boolean" value="false"/>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Courier New" size="11" style="0"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="pageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.pageLabel.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[33, 14]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[33, 14]"/>
</Property>
</Properties>
</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/corecomponents/Bundle.properties" key="DataContentViewerString.nextPageButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="disabledIcon" 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="[55, 23]"/>
</Property>
<Property name="rolloverIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="nextPageButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="pageLabel2">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.pageLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[29, 14]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[29, 14]"/>
</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/corecomponents/Bundle.properties" key="DataContentViewerString.prevPageButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="disabledIcon" 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="[55, 23]"/>
</Property>
<Property name="rolloverIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="prevPageButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="goToPageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.goToPageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="goToPageTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.goToPageTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="goToPageTextFieldActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JComboBox" name="languageCombo">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="0"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.languageCombo.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="languageComboActionPerformed"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new javax.swing.JComboBox&lt;&gt;()"/>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;SCRIPT&gt;"/>
</AuxValues>
</Component>
<Component class="javax.swing.JLabel" name="languageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.languageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.languageLabel.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<Dimension value="[638, 400]"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JScrollPane" name="jScrollPane2">
<Properties>
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
<Property name="verticalScrollBarPolicy" type="int" value="21"/>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel2">
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="pageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" min="-2" max="-2" attributes="0"/>
<Component id="currentPageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="ofLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="totalPageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="50" max="-2" attributes="0"/>
<Component id="pageLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="prevPageButton" min="-2" pref="23" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="nextPageButton" min="-2" pref="23" max="-2" attributes="0"/>
<EmptySpace type="separate" min="-2" max="-2" attributes="0"/>
<Component id="goToPageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="goToPageTextField" min="-2" pref="79" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="33" max="-2" attributes="0"/>
<Component id="languageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="languageCombo" min="-2" pref="155" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
<Component id="pageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="currentPageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="ofLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="totalPageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="pageLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="nextPageButton" alignment="0" min="-2" pref="23" max="-2" attributes="0"/>
<Component id="prevPageButton" alignment="0" min="-2" pref="23" max="-2" attributes="0"/>
<Component id="goToPageLabel" min="-2" max="-2" attributes="0"/>
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
<Component id="goToPageTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="languageCombo" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="languageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="totalPageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.totalPageLabel.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="ofLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.ofLabel.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="currentPageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.currentPageLabel.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="pageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.pageLabel.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[33, 14]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[33, 14]"/>
</Property>
</Properties>
</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/corecomponents/Bundle.properties" key="DataContentViewerString.nextPageButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="disabledIcon" 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="[55, 23]"/>
</Property>
<Property name="rolloverIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="nextPageButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="pageLabel2">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.pageLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[29, 14]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[29, 14]"/>
</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/corecomponents/Bundle.properties" key="DataContentViewerString.prevPageButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="disabledIcon" 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="[55, 23]"/>
</Property>
<Property name="rolloverIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="prevPageButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="goToPageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.goToPageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="goToPageTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.goToPageTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="goToPageTextFieldActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JComboBox" name="languageCombo">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="0"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.languageCombo.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="languageComboActionPerformed"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new javax.swing.JComboBox&lt;&gt;()"/>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;SCRIPT&gt;"/>
</AuxValues>
</Component>
<Component class="javax.swing.JLabel" name="languageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.languageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.languageLabel.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -100,12 +100,10 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
rightClickMenu = new javax.swing.JPopupMenu();
copyMenuItem = new javax.swing.JMenuItem();
selectAllMenuItem = new javax.swing.JMenuItem();
jPanel1 = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
outputViewPane = new JTextPane(){
public boolean getScrollableTracksViewportWidth() {
return (getSize().width < 400);
}};
outputViewPane = new javax.swing.JTextPane();
jScrollPane2 = new javax.swing.JScrollPane();
jPanel2 = new javax.swing.JPanel();
totalPageLabel = new javax.swing.JLabel();
ofLabel = new javax.swing.JLabel();
currentPageLabel = new javax.swing.JLabel();
@ -125,10 +123,8 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
rightClickMenu.add(selectAllMenuItem);
setMinimumSize(new java.awt.Dimension(5, 5));
setPreferredSize(new java.awt.Dimension(100, 144));
jPanel1.setPreferredSize(new java.awt.Dimension(640, 424));
jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
jScrollPane1.setPreferredSize(new java.awt.Dimension(640, 402));
outputViewPane.setEditable(false);
@ -136,6 +132,9 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
outputViewPane.setPreferredSize(new java.awt.Dimension(638, 400));
jScrollPane1.setViewportView(outputViewPane);
jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
jScrollPane2.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
totalPageLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerString.class, "DataContentViewerString.totalPageLabel.text_1")); // NOI18N
ofLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerString.class, "DataContentViewerString.ofLabel.text_1")); // NOI18N
@ -199,11 +198,11 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
languageLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerString.class, "DataContentViewerString.languageLabel.text")); // NOI18N
languageLabel.setToolTipText(org.openide.util.NbBundle.getMessage(DataContentViewerString.class, "DataContentViewerString.languageLabel.toolTipText")); // NOI18N
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap()
.addComponent(pageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
@ -225,39 +224,41 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
.addGap(33, 33, 33)
.addComponent(languageLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(languageCombo, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addComponent(languageCombo, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(pageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(currentPageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(ofLabel)
.addComponent(totalPageLabel))
.addComponent(pageLabel2, 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(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(goToPageLabel)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(goToPageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(languageCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(languageLabel)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 29, Short.MAX_VALUE))
jPanel2Layout.setVerticalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(pageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(currentPageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(ofLabel)
.addComponent(totalPageLabel))
.addComponent(pageLabel2, 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(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(goToPageLabel)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(goToPageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(languageCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(languageLabel))
);
jScrollPane2.setViewportView(jPanel2);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 728, Short.MAX_VALUE)
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 100, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 58, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 25, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
@ -314,8 +315,9 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
private javax.swing.JLabel currentPageLabel;
private javax.swing.JLabel goToPageLabel;
private javax.swing.JTextField goToPageTextField;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JComboBox<SCRIPT> languageCombo;
private javax.swing.JLabel languageLabel;
private javax.swing.JButton nextPageButton;

View File

@ -257,18 +257,18 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
* Used by subclasses of AbstractAbstractFileNode to add the tags property
* to their sheets.
*
* @param ss the modifiable Sheet.Set returned by
* @param sheetSet the modifiable Sheet.Set returned by
* Sheet.get(Sheet.PROPERTIES)
*/
@NbBundle.Messages("AbstractAbstractFileNode.tagsProperty.displayName=Tags")
protected void addTagProperty(Sheet.Set ss) {
protected void addTagProperty(Sheet.Set sheetSet) {
List<ContentTag> tags = new ArrayList<>();
try {
tags.addAll(Case.getOpenCase().getServices().getTagsManager().getContentTagsByContent(content));
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Failed to get tags for content " + content.getName(), ex);
}
ss.put(new NodeProperty<>("Tags", AbstractAbstractFileNode_tagsProperty_displayName(),
sheetSet.put(new NodeProperty<>("Tags", AbstractAbstractFileNode_tagsProperty_displayName(),
NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName())
.distinct()
.collect(Collectors.joining(", "))));

View File

@ -63,11 +63,11 @@ public abstract class AbstractFsContentNode<T extends AbstractFile> extends Abst
@Override
@NbBundle.Messages("AbstractFsContentNode.noDesc.text=no description")
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
Map<String, Object> map = new LinkedHashMap<>();
@ -76,16 +76,16 @@ public abstract class AbstractFsContentNode<T extends AbstractFile> extends Abst
final String NO_DESCR = Bundle.AbstractFsContentNode_noDesc_text();
for (AbstractFilePropertyType propType : AbstractFilePropertyType.values()) {
final String propString = propType.toString();
ss.put(new NodeProperty<>(propString, propString, NO_DESCR, map.get(propString)));
sheetSet.put(new NodeProperty<>(propString, propString, NO_DESCR, map.get(propString)));
}
if (directoryBrowseMode) {
ss.put(new NodeProperty<>(HIDE_PARENT, HIDE_PARENT, HIDE_PARENT, HIDE_PARENT));
sheetSet.put(new NodeProperty<>(HIDE_PARENT, HIDE_PARENT, HIDE_PARENT, HIDE_PARENT));
}
// add tags property to the sheet
addTagProperty(ss);
addTagProperty(sheetSet);
return s;
return sheet;
}
}

View File

@ -32,6 +32,6 @@ public interface AutopsyVisitableItem {
*
* @return visitor return value
*/
public <T> T accept(AutopsyItemVisitor<T> v);
public <T> T accept(AutopsyItemVisitor<T> visitor);
}

View File

@ -314,17 +314,17 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
Map<String, Object> map = new LinkedHashMap<>();
fillPropertyMap(map, artifact);
ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.name"),
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.displayName"),
NO_DESCR,
this.getSourceName()));
@ -333,11 +333,11 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
if (attribute != null) {
BlackboardArtifact associatedArtifact = Case.getOpenCase().getSleuthkitCase().getBlackboardArtifact(attribute.getValueLong());
ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.artifactType.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.artifactType.name"),
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.artifactType.displayName"),
NO_DESCR,
associatedArtifact.getDisplayName() + " " + NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.artifact.displayName")));
ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.artifactDetails.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.artifactDetails.name"),
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.artifactDetails.displayName"),
NO_DESCR,
associatedArtifact.getShortDescription()));
@ -348,7 +348,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
}
for (Map.Entry<String, Object> entry : map.entrySet()) {
ss.put(new NodeProperty<>(entry.getKey(),
sheetSet.put(new NodeProperty<>(entry.getKey(),
entry.getKey(),
NO_DESCR,
entry.getValue()));
@ -357,7 +357,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
//append custom node properties
if (customProperties != null) {
for (NodeProperty<? extends Object> np : customProperties) {
ss.put(np);
sheetSet.put(np);
}
}
@ -375,11 +375,11 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
actualMimeType = ""; //NON-NLS
}
}
ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.ext.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.ext.name"),
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.ext.displayName"),
NO_DESCR,
ext));
ss.put(new NodeProperty<>(
sheetSet.put(new NodeProperty<>(
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.mimeType.name"),
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.mimeType.displayName"),
NO_DESCR,
@ -395,7 +395,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
}
if (sourcePath.isEmpty() == false) {
ss.put(new NodeProperty<>(
sheetSet.put(new NodeProperty<>(
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.filePath.name"),
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.filePath.displayName"),
NO_DESCR,
@ -404,27 +404,27 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
if (Arrays.asList(SHOW_FILE_METADATA).contains(artifactTypeId)) {
AbstractFile file = associated instanceof AbstractFile ? (AbstractFile) associated : null;
ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileModifiedTime.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileModifiedTime.name"),
NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileModifiedTime.displayName"),
"",
file == null ? "" : ContentUtils.getStringTime(file.getMtime(), file)));
ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileChangedTime.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileChangedTime.name"),
NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileChangedTime.displayName"),
"",
file == null ? "" : ContentUtils.getStringTime(file.getCtime(), file)));
ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileAccessedTime.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileAccessedTime.name"),
NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileAccessedTime.displayName"),
"",
file == null ? "" : ContentUtils.getStringTime(file.getAtime(), file)));
ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileCreatedTime.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileCreatedTime.name"),
NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileCreatedTime.displayName"),
"",
file == null ? "" : ContentUtils.getStringTime(file.getCrtime(), file)));
ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileSize.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileSize.name"),
NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileSize.displayName"),
"",
associated.getSize()));
ss.put(new NodeProperty<>(Bundle.BlackboardArtifactNode_createSheet_artifactMD5_name(),
sheetSet.put(new NodeProperty<>(Bundle.BlackboardArtifactNode_createSheet_artifactMD5_name(),
Bundle.BlackboardArtifactNode_createSheet_artifactMD5_displayName(),
"",
file == null ? "" : StringUtils.defaultString(file.getMd5Hash())));
@ -443,7 +443,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
}
if (dataSourceStr.isEmpty() == false) {
ss.put(new NodeProperty<>(
sheetSet.put(new NodeProperty<>(
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.dataSrc.name"),
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.dataSrc.displayName"),
NO_DESCR,
@ -451,21 +451,21 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
}
}
addTagProperty(ss);
addTagProperty(sheetSet);
return s;
return sheet;
}
/**
* Used by (subclasses of) BlackboardArtifactNode to add the tags property
* to their sheets.
*
* @param ss the modifiable Sheet.Set returned by
* @param sheetSet the modifiable Sheet.Set returned by
* Sheet.get(Sheet.PROPERTIES)
*/
@NbBundle.Messages({
"BlackboardArtifactNode.createSheet.tags.displayName=Tags"})
protected void addTagProperty(Sheet.Set ss) throws MissingResourceException {
protected void addTagProperty(Sheet.Set sheetSet) throws MissingResourceException {
// add properties for tags
List<Tag> tags = new ArrayList<>();
try {
@ -474,7 +474,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
} catch (TskCoreException | NoCurrentCaseException ex) {
LOGGER.log(Level.SEVERE, "Failed to get tags for artifact " + artifact.getDisplayName(), ex);
}
ss.put(new NodeProperty<>("Tags", Bundle.BlackboardArtifactNode_createSheet_tags_displayName(),
sheetSet.put(new NodeProperty<>("Tags", Bundle.BlackboardArtifactNode_createSheet_tags_displayName(),
NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", "))));
}
@ -591,8 +591,8 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
/**
@ -630,7 +630,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
}
@Override
public <T> T accept(ContentNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(ContentNodeVisitor<T> visitor) {
return visitor.visit(this);
}
}

View File

@ -138,8 +138,8 @@ public class BlackboardArtifactTagNode extends DisplayableItemNode {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override

View File

@ -44,5 +44,5 @@ abstract class ContentNode extends DisplayableItemNode {
*
* @return visitor's visit return value
*/
public abstract <T> T accept(ContentNodeVisitor<T> v);
public abstract <T> T accept(ContentNodeVisitor<T> visitor);
}

View File

@ -134,8 +134,8 @@ class ContentTagNode extends DisplayableItemNode {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override

View File

@ -27,7 +27,7 @@ public class DataSources implements AutopsyVisitableItem {
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
}

View File

@ -127,23 +127,23 @@ public class DataSourcesNode extends DisplayableItemNode {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "DataSourcesNode.createSheet.name.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "DataSourcesNode.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "DataSourcesNode.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "DataSourcesNode.createSheet.name.desc"),
NAME));
return s;
return sheet;
}
}

View File

@ -96,8 +96,8 @@ public class DeletedContent implements AutopsyVisitableItem {
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
}
@ -115,8 +115,8 @@ public class DeletedContent implements AutopsyVisitableItem {
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
public SleuthkitCase getSleuthkitCase() {
@ -141,8 +141,8 @@ public class DeletedContent implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -150,18 +150,18 @@ public class DeletedContent implements AutopsyVisitableItem {
"DeletedContent.createSheet.name.displayName=Name",
"DeletedContent.createSheet.name.desc=no description"})
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>("Name", //NON-NLS
sheetSet.put(new NodeProperty<>("Name", //NON-NLS
Bundle.DeletedContent_createSheet_name_displayName(),
Bundle.DeletedContent_createSheet_name_desc(),
NAME));
return s;
return sheet;
}
@Override
@ -320,8 +320,8 @@ public class DeletedContent implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -329,19 +329,19 @@ public class DeletedContent implements AutopsyVisitableItem {
"DeletedContent.createSheet.filterType.displayName=Type",
"DeletedContent.createSheet.filterType.desc=no description"})
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>("Type", //NON_NLS
sheetSet.put(new NodeProperty<>("Type", //NON_NLS
Bundle.DeletedContent_createSheet_filterType_displayName(),
Bundle.DeletedContent_createSheet_filterType_desc(),
filter.getDisplayName()));
return s;
return sheet;
}
@Override

View File

@ -104,13 +104,13 @@ public class DirectoryNode extends AbstractFsContentNode<AbstractFile> {
}
@Override
public <T> T accept(ContentNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(ContentNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override

View File

@ -95,8 +95,8 @@ public class EmailExtracted implements AutopsyVisitableItem {
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
private final class EmailResults extends Observable {
@ -193,25 +193,25 @@ public class EmailExtracted implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "EmailExtracted.createSheet.name.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "EmailExtracted.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "EmailExtracted.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "EmailExtracted.createSheet.name.desc"),
getName()));
return s;
return sheet;
}
@Override
@ -339,19 +339,19 @@ public class EmailExtracted implements AutopsyVisitableItem {
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "EmailExtracted.createSheet.name.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "EmailExtracted.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "EmailExtracted.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "EmailExtracted.createSheet.name.desc"),
getName()));
return s;
return sheet;
}
@Override
@ -360,8 +360,8 @@ public class EmailExtracted implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -435,24 +435,24 @@ public class EmailExtracted implements AutopsyVisitableItem {
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "EmailExtracted.createSheet.name.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "EmailExtracted.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "EmailExtracted.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "EmailExtracted.createSheet.name.desc"),
getName()));
return s;
return sheet;
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override

View File

@ -85,8 +85,8 @@ public final class EmptyNode extends AbstractNode {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override

View File

@ -64,8 +64,8 @@ public class ExtractedContent implements AutopsyVisitableItem {
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
public SleuthkitCase getSleuthkitCase() {
@ -152,24 +152,24 @@ public class ExtractedContent implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ExtractedContentNode.createSheet.name.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ExtractedContentNode.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "ExtractedContentNode.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "ExtractedContentNode.createSheet.name.desc"),
NAME));
return s;
return sheet;
}
@Override
@ -342,29 +342,29 @@ public class ExtractedContent implements AutopsyVisitableItem {
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.name"),
NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.displayName"),
NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.desc"),
type.getDisplayName()));
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.name"),
NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.displayName"),
NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.desc"),
childCount));
return s;
return sheet;
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override

View File

@ -92,8 +92,8 @@ public class FileSize implements AutopsyVisitableItem {
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
}
@ -107,8 +107,8 @@ public class FileSize implements AutopsyVisitableItem {
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
public SleuthkitCase getSleuthkitCase() {
@ -138,24 +138,24 @@ public class FileSize implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileSize.createSheet.name.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileSize.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "FileSize.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "FileSize.createSheet.name.desc"),
NAME));
return s;
return sheet;
}
@Override
@ -329,25 +329,25 @@ public class FileSize implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileSize.createSheet.filterType.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileSize.createSheet.filterType.name"),
NbBundle.getMessage(this.getClass(), "FileSize.createSheet.filterType.displayName"),
NbBundle.getMessage(this.getClass(), "FileSize.createSheet.filterType.desc"),
filter.getDisplayName()));
return s;
return sheet;
}
@Override

View File

@ -85,8 +85,8 @@ public final class FileTypes implements AutopsyVisitableItem {
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
SleuthkitCase getSleuthkitCase() {
@ -137,8 +137,8 @@ public final class FileTypes implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -147,19 +147,19 @@ public final class FileTypes implements AutopsyVisitableItem {
"FileTypes.createSheet.name.displayName=Name",
"FileTypes.createSheet.name.desc=no description"})
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(Bundle.FileTypes_createSheet_name_name(),
sheetSet.put(new NodeProperty<>(Bundle.FileTypes_createSheet_name_name(),
Bundle.FileTypes_createSheet_name_displayName(),
Bundle.FileTypes_createSheet_name_desc(),
NAME
));
return s;
return sheet;
}
@Override

View File

@ -65,8 +65,8 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
long filteringDataSourceObjId() {
@ -181,17 +181,17 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
if (filter != null && (filter.equals(FileTypesByExtension.RootFilter.TSK_DOCUMENT_FILTER) || filter.equals(FileTypesByExtension.RootFilter.TSK_EXECUTABLE_FILTER))) {
String extensions = "";
@ -199,11 +199,11 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
extensions += "'" + ext + "', ";
}
extensions = extensions.substring(0, extensions.lastIndexOf(','));
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.name"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.displayName"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.desc"), extensions));
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.name"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.displayName"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.desc"), extensions));
} else {
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.name.name"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.name.displayName"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.name.desc"), getDisplayName()));
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.name.name"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.name.displayName"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.name.desc"), getDisplayName()));
}
return s;
return sheet;
}
@Override
@ -301,28 +301,28 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.filterType.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.filterType.name"),
NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.filterType.displayName"),
NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.filterType.desc"),
filter.getDisplayName()));
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.name"),
NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.displayName"),
NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.desc"),
String.join(", ", filter.getFilter())));
return s;
return sheet;
}
@Override
@ -470,8 +470,8 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -527,8 +527,8 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -574,8 +574,8 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
@Override

View File

@ -186,8 +186,8 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
long filteringDataSourceObjId() {
@ -237,8 +237,8 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -310,20 +310,20 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByMimeTypeNode.createSheet.mediaType.name"), NbBundle.getMessage(this.getClass(), "FileTypesByMimeTypeNode.createSheet.mediaType.displayName"), NbBundle.getMessage(this.getClass(), "FileTypesByMimeTypeNode.createSheet.mediaType.desc"), getDisplayName()));
return s;
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByMimeTypeNode.createSheet.mediaType.name"), NbBundle.getMessage(this.getClass(), "FileTypesByMimeTypeNode.createSheet.mediaType.displayName"), NbBundle.getMessage(this.getClass(), "FileTypesByMimeTypeNode.createSheet.mediaType.desc"), getDisplayName()));
return sheet;
}
@Override
@ -401,20 +401,20 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
}
@Override
public <T> T accept(DisplayableItemNodeVisitor< T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor< T> visitor) {
return visitor.visit(this);
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByMimeTypeNode.createSheet.mediaSubtype.name"), NbBundle.getMessage(this.getClass(), "FileTypesByMimeTypeNode.createSheet.mediaSubtype.displayName"), NbBundle.getMessage(this.getClass(), "FileTypesByMimeTypeNode.createSheet.mediaSubtype.desc"), getDisplayName()));
return s;
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByMimeTypeNode.createSheet.mediaSubtype.name"), NbBundle.getMessage(this.getClass(), "FileTypesByMimeTypeNode.createSheet.mediaSubtype.displayName"), NbBundle.getMessage(this.getClass(), "FileTypesByMimeTypeNode.createSheet.mediaSubtype.desc"), getDisplayName()));
return sheet;
}
@Override

View File

@ -70,8 +70,8 @@ public class HashsetHits implements AutopsyVisitableItem {
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
/**
@ -160,25 +160,25 @@ public class HashsetHits implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "HashsetHits.createSheet.name.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "HashsetHits.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "HashsetHits.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "HashsetHits.createSheet.name.desc"),
getName()));
return s;
return sheet;
}
@Override
@ -314,24 +314,24 @@ public class HashsetHits implements AutopsyVisitableItem {
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "HashsetHits.createSheet.name.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "HashsetHits.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "HashsetHits.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "HashsetHits.createSheet.name.desc"),
getName()));
return s;
return sheet;
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override

View File

@ -135,38 +135,38 @@ public class ImageNode extends AbstractContentNode<Image> {
"ImageNode.createSheet.deviceId.displayName=Device ID",
"ImageNode.createSheet.deviceId.desc=Device ID of the image"})
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ImageNode.createSheet.name.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ImageNode.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "ImageNode.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "ImageNode.createSheet.name.desc"),
getDisplayName()));
ss.put(new NodeProperty<>(Bundle.ImageNode_createSheet_type_name(),
sheetSet.put(new NodeProperty<>(Bundle.ImageNode_createSheet_type_name(),
Bundle.ImageNode_createSheet_type_displayName(),
Bundle.ImageNode_createSheet_type_desc(),
Bundle.ImageNode_createSheet_type_text()));
ss.put(new NodeProperty<>(Bundle.ImageNode_createSheet_size_name(),
sheetSet.put(new NodeProperty<>(Bundle.ImageNode_createSheet_size_name(),
Bundle.ImageNode_createSheet_size_displayName(),
Bundle.ImageNode_createSheet_size_desc(),
this.content.getSize()));
ss.put(new NodeProperty<>(Bundle.ImageNode_createSheet_sectorSize_name(),
sheetSet.put(new NodeProperty<>(Bundle.ImageNode_createSheet_sectorSize_name(),
Bundle.ImageNode_createSheet_sectorSize_displayName(),
Bundle.ImageNode_createSheet_sectorSize_desc(),
this.content.getSsize()));
ss.put(new NodeProperty<>(Bundle.ImageNode_createSheet_md5_name(),
sheetSet.put(new NodeProperty<>(Bundle.ImageNode_createSheet_md5_name(),
Bundle.ImageNode_createSheet_md5_displayName(),
Bundle.ImageNode_createSheet_md5_desc(),
this.content.getMd5()));
ss.put(new NodeProperty<>(Bundle.ImageNode_createSheet_timezone_name(),
sheetSet.put(new NodeProperty<>(Bundle.ImageNode_createSheet_timezone_name(),
Bundle.ImageNode_createSheet_timezone_displayName(),
Bundle.ImageNode_createSheet_timezone_desc(),
this.content.getTimeZone()));
@ -174,7 +174,7 @@ public class ImageNode extends AbstractContentNode<Image> {
try (CaseDbQuery query = Case.getOpenCase().getSleuthkitCase().executeQuery("SELECT device_id FROM data_source_info WHERE obj_id = " + this.content.getId());) {
ResultSet deviceIdSet = query.getResultSet();
if (deviceIdSet.next()) {
ss.put(new NodeProperty<>(Bundle.ImageNode_createSheet_deviceId_name(),
sheetSet.put(new NodeProperty<>(Bundle.ImageNode_createSheet_deviceId_name(),
Bundle.ImageNode_createSheet_deviceId_displayName(),
Bundle.ImageNode_createSheet_deviceId_desc(),
deviceIdSet.getString("device_id")));
@ -183,12 +183,12 @@ public class ImageNode extends AbstractContentNode<Image> {
logger.log(Level.SEVERE, "Failed to get device id for the following image: " + this.content.getId(), ex);
}
return s;
return sheet;
}
@Override
public <T> T accept(ContentNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(ContentNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -197,8 +197,8 @@ public class ImageNode extends AbstractContentNode<Image> {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override

View File

@ -134,8 +134,8 @@ public class InterestingHits implements AutopsyVisitableItem {
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
/**
@ -156,25 +156,25 @@ public class InterestingHits implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.desc"),
getName()));
return s;
return sheet;
}
@Override
@ -302,24 +302,24 @@ public class InterestingHits implements AutopsyVisitableItem {
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.desc"),
getName()));
return s;
return sheet;
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -392,22 +392,22 @@ public class InterestingHits implements AutopsyVisitableItem {
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.desc"),
getName()));
return s;
return sheet;
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override

View File

@ -73,16 +73,16 @@ public class KeyValueNode extends AbstractNode {
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
// table view drops first column of properties under assumption
// that it contains the node's name
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "KeyValueNode.createSheet.name.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "KeyValueNode.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "KeyValueNode.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "KeyValueNode.createSheet.name.desc"),
data.getName()));
@ -90,13 +90,13 @@ public class KeyValueNode extends AbstractNode {
for (Map.Entry<String, Object> entry : data.getMap().entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
ss.put(new NodeProperty<>(key,
sheetSet.put(new NodeProperty<>(key,
key,
NbBundle.getMessage(this.getClass(), "KeyValueNode.createSheet.map.desc"),
value));
}
return s;
return sheet;
}
/**

View File

@ -326,8 +326,8 @@ public class KeywordHits implements AutopsyVisitableItem {
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
// Created by CreateAutopsyNodeVisitor
@ -346,8 +346,8 @@ public class KeywordHits implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -355,20 +355,20 @@ public class KeywordHits implements AutopsyVisitableItem {
"KeywordHits.createSheet.name.displayName=Name",
"KeywordHits.createSheet.name.desc=no description"})
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(
sheetSet.put(new NodeProperty<>(
KeywordHits_createSheet_name_name(),
KeywordHits_createSheet_name_displayName(),
KeywordHits_createSheet_name_desc(),
getName()));
return s;
return sheet;
}
@Override
@ -547,26 +547,26 @@ public class KeywordHits implements AutopsyVisitableItem {
"KeywordHits.createSheet.numChildren.displayName=Number of Children",
"KeywordHits.createSheet.numChildren.desc=no description"})
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(
sheetSet.put(new NodeProperty<>(
KeywordHits_createSheet_listName_name(),
KeywordHits_createSheet_listName_displayName(),
KeywordHits_createSheet_listName_desc(),
listName));
ss.put(new NodeProperty<>(
sheetSet.put(new NodeProperty<>(
KeywordHits_createSheet_numChildren_name(),
KeywordHits_createSheet_numChildren_displayName(),
KeywordHits_createSheet_numChildren_desc(),
keywordResults.getKeywords(listName).size()));
return s;
return sheet;
}
@Override
@ -575,8 +575,8 @@ public class KeywordHits implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
}
@ -636,8 +636,8 @@ public class KeywordHits implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -645,25 +645,25 @@ public class KeywordHits implements AutopsyVisitableItem {
"KeywordHits.createSheet.filesWithHits.displayName=Files with Hits",
"KeywordHits.createSheet.filesWithHits.desc=no description"})
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(
sheetSet.put(new NodeProperty<>(
KeywordHits_createSheet_listName_name(),
KeywordHits_createSheet_listName_displayName(),
KeywordHits_createSheet_listName_desc(),
getDisplayName()));
ss.put(new NodeProperty<>(
sheetSet.put(new NodeProperty<>(
KeywordHits_createSheet_filesWithHits_name(),
KeywordHits_createSheet_filesWithHits_displayName(),
KeywordHits_createSheet_filesWithHits_desc(),
countTotalDescendants()));
return s;
return sheet;
}
}
@ -777,32 +777,32 @@ public class KeywordHits implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(
sheetSet.put(new NodeProperty<>(
KeywordHits_createSheet_listName_name(),
KeywordHits_createSheet_listName_displayName(),
KeywordHits_createSheet_listName_desc(),
getDisplayName()));
ss.put(new NodeProperty<>(
sheetSet.put(new NodeProperty<>(
KeywordHits_createSheet_filesWithHits_name(),
KeywordHits_createSheet_filesWithHits_displayName(),
KeywordHits_createSheet_filesWithHits_desc(),
keywordResults.getArtifactIds(setName, keyword, instance).size()));
return s;
return sheet;
}
}

View File

@ -71,35 +71,35 @@ public class LayoutFileNode extends AbstractAbstractFileNode<LayoutFile> {
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
Map<String, Object> map = new LinkedHashMap<>();
fillPropertyMap(map);
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "LayoutFileNode.createSheet.name.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "LayoutFileNode.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "LayoutFileNode.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "LayoutFileNode.createSheet.name.desc"),
getName()));
final String NO_DESCR = NbBundle.getMessage(this.getClass(), "LayoutFileNode.createSheet.noDescr.text");
for (Map.Entry<String, Object> entry : map.entrySet()) {
ss.put(new NodeProperty<>(entry.getKey(), entry.getKey(), NO_DESCR, entry.getValue()));
sheetSet.put(new NodeProperty<>(entry.getKey(), entry.getKey(), NO_DESCR, entry.getValue()));
}
// add tags property to the sheet
addTagProperty(ss);
addTagProperty(sheetSet);
return s;
return sheet;
}
@Override
public <T> T accept(ContentNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(ContentNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -108,8 +108,8 @@ public class LayoutFileNode extends AbstractAbstractFileNode<LayoutFile> {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override

View File

@ -48,14 +48,14 @@ public class LocalDirectoryNode extends SpecialDirectoryNode {
"LocalDirectoryNode.createSheet.name.desc=no description",
"LocalDirectoryNode.createSheet.noDesc=no description"})
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(Bundle.LocalDirectoryNode_createSheet_name_name(),
sheetSet.put(new NodeProperty<>(Bundle.LocalDirectoryNode_createSheet_name_name(),
Bundle.LocalDirectoryNode_createSheet_name_displayName(),
Bundle.LocalDirectoryNode_createSheet_name_desc(),
getName()));
@ -67,20 +67,20 @@ public class LocalDirectoryNode extends SpecialDirectoryNode {
final String NO_DESCR = Bundle.LocalDirectoryNode_createSheet_noDesc();
for (Map.Entry<String, Object> entry : map.entrySet()) {
ss.put(new NodeProperty<>(entry.getKey(), entry.getKey(), NO_DESCR, entry.getValue()));
sheetSet.put(new NodeProperty<>(entry.getKey(), entry.getKey(), NO_DESCR, entry.getValue()));
}
addTagProperty(ss);
addTagProperty(sheetSet);
return s;
return sheet;
}
@Override
public <T> T accept(ContentNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(ContentNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
}

View File

@ -67,30 +67,30 @@ public class LocalFileNode extends AbstractAbstractFileNode<AbstractFile> {
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
Map<String, Object> map = new LinkedHashMap<>();
fillPropertyMap(map, getContent());
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "LocalFileNode.createSheet.name.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "LocalFileNode.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "LocalFileNode.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "LocalFileNode.createSheet.name.desc"),
getName()));
final String NO_DESCR = NbBundle.getMessage(this.getClass(), "LocalFileNode.createSheet.noDescr.text");
for (Map.Entry<String, Object> entry : map.entrySet()) {
ss.put(new NodeProperty<>(entry.getKey(), entry.getKey(), NO_DESCR, entry.getValue()));
sheetSet.put(new NodeProperty<>(entry.getKey(), entry.getKey(), NO_DESCR, entry.getValue()));
}
// add tags property to the sheet
addTagProperty(ss);
addTagProperty(sheetSet);
return s;
return sheet;
}
@Override
@ -132,13 +132,13 @@ public class LocalFileNode extends AbstractAbstractFileNode<AbstractFile> {
}
@Override
public <T> T accept(ContentNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(ContentNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override

View File

@ -77,8 +77,8 @@ public class RecentFiles implements AutopsyVisitableItem {
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
}
@ -88,8 +88,8 @@ public class RecentFiles implements AutopsyVisitableItem {
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
public SleuthkitCase getSleuthkitCase() {

View File

@ -56,26 +56,26 @@ public class RecentFilesFilterNode extends DisplayableItemNode {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(
sheetSet.put(new NodeProperty<>(
NbBundle.getMessage(this.getClass(), "RecentFilesFilterNode.createSheet.filterType.name"),
NbBundle.getMessage(this.getClass(), "RecentFilesFilterNode.createSheet.filterType.displayName"),
NbBundle.getMessage(this.getClass(), "RecentFilesFilterNode.createSheet.filterType.desc"),
filter.getDisplayName()));
return s;
return sheet;
}
@Override

View File

@ -30,13 +30,11 @@ import org.sleuthkit.datamodel.SleuthkitCase;
public class RecentFilesNode extends DisplayableItemNode {
private static final String NAME = NbBundle.getMessage(RecentFilesNode.class, "RecentFilesNode.name.text");
private SleuthkitCase skCase;
RecentFilesNode(SleuthkitCase skCase) {
super(Children.create(new RecentFilesChildren(skCase), true), Lookups.singleton(NAME));
super.setName(NAME);
super.setDisplayName(NAME);
this.skCase = skCase;
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/recent_files.png"); //NON-NLS
}
@ -46,24 +44,24 @@ public class RecentFilesNode extends DisplayableItemNode {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "RecentFilesNode.createSheet.name.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "RecentFilesNode.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "RecentFilesNode.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "RecentFilesNode.createSheet.name.desc"),
NAME));
return s;
return sheet;
}
@Override

View File

@ -32,8 +32,8 @@ public class Results implements AutopsyVisitableItem {
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
public SleuthkitCase getSleuthkitCase() {

View File

@ -55,8 +55,8 @@ public class ResultsNode extends DisplayableItemNode {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -65,19 +65,19 @@ public class ResultsNode extends DisplayableItemNode {
"ResultsNode.createSheet.name.displayName=Name",
"ResultsNode.createSheet.name.desc=no description"})
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(Bundle.ResultsNode_createSheet_name_name(),
sheetSet.put(new NodeProperty<>(Bundle.ResultsNode_createSheet_name_name(),
Bundle.ResultsNode_createSheet_name_displayName(),
Bundle.ResultsNode_createSheet_name_desc(),
NAME
));
return s;
return sheet;
}
@Override

View File

@ -99,13 +99,13 @@ public class SlackFileNode extends AbstractFsContentNode<AbstractFile> {
}
@Override
public <T> T accept(ContentNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(ContentNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
// Given a file, returns the correct icon for said

View File

@ -58,8 +58,8 @@ public class Tags implements AutopsyVisitableItem {
private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
/**
@ -96,8 +96,8 @@ public class Tags implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -266,10 +266,10 @@ public class Tags implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
// See classes derived from DisplayableItemNodeVisitor<AbstractNode>
// for behavior added using the Visitor pattern.
return v.visit(this);
return visitor.visit(this);
}
@Override
@ -369,8 +369,8 @@ public class Tags implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -468,8 +468,8 @@ public class Tags implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override

View File

@ -32,8 +32,8 @@ public class Views implements AutopsyVisitableItem {
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
public SleuthkitCase getSleuthkitCase() {

View File

@ -60,24 +60,24 @@ public class ViewsNode extends DisplayableItemNode {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ViewsNode.createSheet.name.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ViewsNode.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "ViewsNode.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "ViewsNode.createSheet.name.desc"),
NAME));
return s;
return sheet;
}
@Override

View File

@ -75,14 +75,14 @@ public class VirtualDirectoryNode extends SpecialDirectoryNode {
"VirtualDirectoryNode.createSheet.deviceId.displayName=Device ID",
"VirtualDirectoryNode.createSheet.deviceId.desc=Device ID of the image"})
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "VirtualDirectoryNode.createSheet.name.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "VirtualDirectoryNode.createSheet.name.name"),
NbBundle.getMessage(this.getClass(),
"VirtualDirectoryNode.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "VirtualDirectoryNode.createSheet.name.desc"),
@ -94,22 +94,22 @@ public class VirtualDirectoryNode extends SpecialDirectoryNode {
final String NO_DESCR = NbBundle.getMessage(this.getClass(), "VirtualDirectoryNode.createSheet.noDesc");
for (Map.Entry<String, Object> entry : map.entrySet()) {
ss.put(new NodeProperty<>(entry.getKey(), entry.getKey(), NO_DESCR, entry.getValue()));
sheetSet.put(new NodeProperty<>(entry.getKey(), entry.getKey(), NO_DESCR, entry.getValue()));
}
addTagProperty(ss);
addTagProperty(sheetSet);
} else {
ss.put(new NodeProperty<>(Bundle.VirtualDirectoryNode_createSheet_type_name(),
sheetSet.put(new NodeProperty<>(Bundle.VirtualDirectoryNode_createSheet_type_name(),
Bundle.VirtualDirectoryNode_createSheet_type_displayName(),
Bundle.VirtualDirectoryNode_createSheet_type_desc(),
Bundle.VirtualDirectoryNode_createSheet_type_text()));
ss.put(new NodeProperty<>(Bundle.VirtualDirectoryNode_createSheet_size_name(),
sheetSet.put(new NodeProperty<>(Bundle.VirtualDirectoryNode_createSheet_size_name(),
Bundle.VirtualDirectoryNode_createSheet_size_displayName(),
Bundle.VirtualDirectoryNode_createSheet_size_desc(),
this.content.getSize()));
try (SleuthkitCase.CaseDbQuery query = Case.getOpenCase().getSleuthkitCase().executeQuery("SELECT time_zone FROM data_source_info WHERE obj_id = " + this.content.getId())) {
ResultSet timeZoneSet = query.getResultSet();
if (timeZoneSet.next()) {
ss.put(new NodeProperty<>(Bundle.VirtualDirectoryNode_createSheet_timezone_name(),
sheetSet.put(new NodeProperty<>(Bundle.VirtualDirectoryNode_createSheet_timezone_name(),
Bundle.VirtualDirectoryNode_createSheet_timezone_displayName(),
Bundle.VirtualDirectoryNode_createSheet_timezone_desc(),
timeZoneSet.getString("time_zone")));
@ -120,7 +120,7 @@ public class VirtualDirectoryNode extends SpecialDirectoryNode {
try (SleuthkitCase.CaseDbQuery query = Case.getOpenCase().getSleuthkitCase().executeQuery("SELECT device_id FROM data_source_info WHERE obj_id = " + this.content.getId());) {
ResultSet deviceIdSet = query.getResultSet();
if (deviceIdSet.next()) {
ss.put(new NodeProperty<>(Bundle.VirtualDirectoryNode_createSheet_deviceId_name(),
sheetSet.put(new NodeProperty<>(Bundle.VirtualDirectoryNode_createSheet_deviceId_name(),
Bundle.VirtualDirectoryNode_createSheet_deviceId_displayName(),
Bundle.VirtualDirectoryNode_createSheet_deviceId_desc(),
deviceIdSet.getString("device_id")));
@ -131,16 +131,16 @@ public class VirtualDirectoryNode extends SpecialDirectoryNode {
}
return s;
return sheet;
}
@Override
public <T> T accept(ContentNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(ContentNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
}

View File

@ -150,44 +150,44 @@ public class VolumeNode extends AbstractContentNode<Volume> {
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.name.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.name.desc"),
this.getDisplayName()));
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.id.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.id.name"),
NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.id.displayName"),
NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.id.desc"),
content.getAddr()));
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.startSector.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.startSector.name"),
NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.startSector.displayName"),
NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.startSector.desc"),
content.getStart()));
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.lenSectors.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.lenSectors.name"),
NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.lenSectors.displayName"),
NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.lenSectors.desc"),
content.getLength()));
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.description.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.description.name"),
NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.description.displayName"),
NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.description.desc"),
content.getDescription()));
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.flags.name"),
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.flags.name"),
NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.flags.displayName"),
NbBundle.getMessage(this.getClass(), "VolumeNode.createSheet.flags.desc"),
content.getFlagsAsString()));
return s;
return sheet;
}
@Override
public <T> T accept(ContentNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(ContentNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -196,8 +196,8 @@ public class VolumeNode extends AbstractContentNode<Volume> {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override

View File

@ -115,8 +115,8 @@ final public class Accounts implements AutopsyVisitableItem {
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
/**
@ -207,8 +207,8 @@ final public class Accounts implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -483,8 +483,8 @@ final public class Accounts implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -627,8 +627,8 @@ final public class Accounts implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -830,8 +830,8 @@ final public class Accounts implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -1026,8 +1026,8 @@ final public class Accounts implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -1215,8 +1215,8 @@ final public class Accounts implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -1394,8 +1394,8 @@ final public class Accounts implements AutopsyVisitableItem {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
@ -1403,13 +1403,13 @@ final public class Accounts implements AutopsyVisitableItem {
return getClass().getName();
}
private Sheet.Set getPropertySet(Sheet s) {
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
private Sheet.Set getPropertySet(Sheet sheet) {
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
return ss;
return sheetSet;
}
@Override

View File

@ -18,7 +18,6 @@
*/
package org.sleuthkit.autopsy.guiutils;
import java.awt.Color;
import java.awt.Component;
import java.time.Duration;
import javax.swing.JTable;
@ -41,36 +40,47 @@ public class DurationCellRenderer extends GrayableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (value instanceof Long) {
{
Duration d = Duration.ofMillis((long) value);
if (d.isNegative()) {
d = Duration.ofMillis(-(long) value);
}
String result;
long days = d.toDays();
long hours = d.minusDays(days).toHours();
long minutes = d.minusDays(days).minusHours(hours).toMinutes();
long seconds = d.minusDays(days).minusHours(hours).minusMinutes(minutes).getSeconds();
if (minutes > 0) {
if (hours > 0) {
if (days > 0) {
result = days + " d " + hours + " h " + minutes + " m " + seconds + " s";
} else {
result = hours + " h " + minutes + " m " + seconds + " s";
}
} else {
result = minutes + " m " + seconds + " s";
}
} else {
result = seconds + " s";
}
setText(result);
setText(DurationCellRenderer.longToDurationString((long) value));
}
}
grayCellIfTableNotEnabled(table, isSelected);
return this;
}
/**
* Convert a duration represented by a long to a human readable string with
* with days, hours, minutes, and seconds components.
*
* @param duration - the representation of the duration in long form
*
* @return - the representation of the duration in String form.
*/
public static String longToDurationString(long duration) {
Duration d = Duration.ofMillis(duration);
if (d.isNegative()) {
d = Duration.ofMillis(-duration);
}
String result;
long days = d.toDays();
long hours = d.minusDays(days).toHours();
long minutes = d.minusDays(days).minusHours(hours).toMinutes();
long seconds = d.minusDays(days).minusHours(hours).minusMinutes(minutes).getSeconds();
if (minutes > 0) {
if (hours > 0) {
if (days > 0) {
result = days + " d " + hours + " h " + minutes + " m " + seconds + " s";
} else {
result = hours + " h " + minutes + " m " + seconds + " s";
}
} else {
result = minutes + " m " + seconds + " s";
}
} else {
result = seconds + " s";
}
return result;
}
}

View File

@ -0,0 +1,859 @@
/*
* 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.healthmonitor;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;
import java.util.List;
import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import org.apache.commons.dbcp2.BasicDataSource;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.core.UserPreferencesException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.ThreadUtils;
import org.sleuthkit.datamodel.CaseDbConnectionInfo;
import org.sleuthkit.datamodel.CaseDbSchemaVersionNumber;
import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Class for recording data on the health of the system.
*
* For timing data:
* Modules will call getTimingMetric() before the code to be timed to get a TimingMetric object
* Modules will call submitTimingMetric() with the obtained TimingMetric object to log it
*/
public final class EnterpriseHealthMonitor implements PropertyChangeListener {
private final static Logger logger = Logger.getLogger(EnterpriseHealthMonitor.class.getName());
private final static String DATABASE_NAME = "EnterpriseHealthMonitor";
private final static String MODULE_NAME = "EnterpriseHealthMonitor";
private final static String IS_ENABLED_KEY = "is_enabled";
private final static long DATABASE_WRITE_INTERVAL = 60; // Minutes
public static final CaseDbSchemaVersionNumber CURRENT_DB_SCHEMA_VERSION
= new CaseDbSchemaVersionNumber(1, 0);
private static final AtomicBoolean isEnabled = new AtomicBoolean(false);
private static EnterpriseHealthMonitor instance;
private final ExecutorService healthMonitorExecutor;
private static final String HEALTH_MONITOR_EVENT_THREAD_NAME = "Health-Monitor-Event-Listener-%d";
private ScheduledThreadPoolExecutor healthMonitorOutputTimer;
private final Map<String, TimingInfo> timingInfoMap;
private static final int CONN_POOL_SIZE = 10;
private BasicDataSource connectionPool = null;
private String hostName;
private EnterpriseHealthMonitor() throws HealthMonitorException {
// Create the map to collect timing metrics. The map will exist regardless
// of whether the monitor is enabled.
timingInfoMap = new HashMap<>();
// Set up the executor to handle case events
healthMonitorExecutor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(HEALTH_MONITOR_EVENT_THREAD_NAME).build());
// Get the host name
try {
hostName = java.net.InetAddress.getLocalHost().getHostName();
} catch (java.net.UnknownHostException ex) {
// Continue on, but log the error and generate a UUID to use for this session
hostName = UUID.randomUUID().toString();
logger.log(Level.SEVERE, "Unable to look up host name - falling back to UUID " + hostName, ex);
}
// Read from module settings to determine if the module is enabled
if (ModuleSettings.settingExists(MODULE_NAME, IS_ENABLED_KEY)) {
if(ModuleSettings.getConfigSetting(MODULE_NAME, IS_ENABLED_KEY).equals("true")){
isEnabled.set(true);
try {
activateMonitor();
} catch (HealthMonitorException ex) {
// If we failed to activate it, then disable the monitor
logger.log(Level.SEVERE, "Health monitor activation failed - disabling health monitor");
setEnabled(false);
throw ex;
}
return;
}
}
isEnabled.set(false);
}
/**
* Get the instance of the EnterpriseHealthMonitor
* @return the instance
* @throws HealthMonitorException
*/
synchronized static EnterpriseHealthMonitor getInstance() throws HealthMonitorException {
if (instance == null) {
instance = new EnterpriseHealthMonitor();
Case.addPropertyChangeListener(instance);
}
return instance;
}
/**
* Activate the health monitor.
* Creates/initialized the database (if needed), clears any existing metrics
* out of the maps, and sets up the timer for writing to the database.
* @throws HealthMonitorException
*/
private synchronized void activateMonitor() throws HealthMonitorException {
logger.log(Level.INFO, "Activating Servies Health Monitor");
if (!UserPreferences.getIsMultiUserModeEnabled()) {
throw new HealthMonitorException("Multi user mode is not enabled - can not activate health monitor");
}
// Set up database (if needed)
try (CoordinationService.Lock lock = getExclusiveDbLock()) {
if(lock == null) {
throw new HealthMonitorException("Error getting database lock");
}
// Check if the database exists
if (! databaseExists()) {
// If not, create a new one
createDatabase();
}
if( ! databaseIsInitialized()) {
initializeDatabaseSchema();
}
} catch (CoordinationService.CoordinationServiceException ex) {
throw new HealthMonitorException("Error releasing database lock", ex);
}
// Clear out any old data
timingInfoMap.clear();
// Start the timer for database writes
startTimer();
}
/**
* Deactivate the health monitor.
* This should only be used when disabling the monitor, not when Autopsy is closing.
* Clears out any metrics that haven't been written, stops the database write timer,
* and shuts down the connection pool.
* @throws HealthMonitorException
*/
private synchronized void deactivateMonitor() throws HealthMonitorException {
logger.log(Level.INFO, "Deactivating Servies Health Monitor");
// Clear out the collected data
timingInfoMap.clear();
// Stop the timer
stopTimer();
// Shut down the connection pool
shutdownConnections();
}
/**
* Start the ScheduledThreadPoolExecutor that will handle the database writes.
*/
private synchronized void startTimer() {
// Make sure the previous executor (if it exists) has been stopped
stopTimer();
healthMonitorOutputTimer = new ScheduledThreadPoolExecutor(1, new ThreadFactoryBuilder().setNameFormat("health_monitor_timer").build());
healthMonitorOutputTimer.scheduleWithFixedDelay(new DatabaseWriteTask(), DATABASE_WRITE_INTERVAL, DATABASE_WRITE_INTERVAL, TimeUnit.MINUTES);
}
/**
* Stop the ScheduledThreadPoolExecutor to prevent further database writes.
*/
private synchronized void stopTimer() {
if(healthMonitorOutputTimer != null) {
ThreadUtils.shutDownTaskExecutor(healthMonitorOutputTimer);
}
}
/**
* Called from the installer to set up the Health Monitor instance at startup.
* @throws HealthMonitorException
*/
static synchronized void startUpIfEnabled() throws HealthMonitorException {
getInstance();
}
/**
* Enabled/disable the health monitor.
* @param enabled true to enable the monitor, false to disable it
* @throws HealthMonitorException
*/
static synchronized void setEnabled(boolean enabled) throws HealthMonitorException {
if(enabled == isEnabled.get()) {
// The setting has not changed, so do nothing
return;
}
if(enabled) {
getInstance().activateMonitor();
// If activateMonitor fails, we won't update either of these
ModuleSettings.setConfigSetting(MODULE_NAME, IS_ENABLED_KEY, "true");
isEnabled.set(true);
} else {
ModuleSettings.setConfigSetting(MODULE_NAME, IS_ENABLED_KEY, "false");
isEnabled.set(false);
getInstance().deactivateMonitor();
}
}
/**
* Get a metric that will measure the time to execute a section of code.
* Call this before the section of code to be timed and then
* submit it afterward using submitTimingMetric().
* This method is safe to call regardless of whether the Enterprise Health
* Monitor is enabled.
* @param name A short but descriptive name describing the code being timed.
* This name will appear in the UI.
* @return The TimingMetric object
*/
public static TimingMetric getTimingMetric(String name) {
if(isEnabled.get()) {
return new TimingMetric(name);
}
return null;
}
/**
* Submit the metric that was previously obtained through getTimingMetric().
* Call this immediately after the section of code being timed.
* This method is safe to call regardless of whether the Enterprise Health
* Monitor is enabled.
* @param metric The TimingMetric object obtained from getTimingMetric()
*/
public static void submitTimingMetric(TimingMetric metric) {
if(isEnabled.get() && (metric != null)) {
metric.stopTiming();
try {
getInstance().addTimingMetric(metric);
} catch (HealthMonitorException ex) {
// We don't want calling methods to have to check for exceptions, so just log it
logger.log(Level.SEVERE, "Error adding timing metric", ex);
}
}
}
/**
* Submit the metric that was previously obtained through getTimingMetric(),
* incorporating a count that the time should be divided by.
* Call this immediately after the section of code being timed.
* This method is safe to call regardless of whether the Enterprise Health
* Monitor is enabled.
* @param metric The TimingMetric object obtained from getTimingMetric()
* @param normalization The number to divide the time by (a zero here will be treated as a one)
*/
public static void submitNormalizedTimingMetric(TimingMetric metric, long normalization) {
if(isEnabled.get() && (metric != null)) {
metric.stopTiming();
try {
metric.normalize(normalization);
getInstance().addTimingMetric(metric);
} catch (HealthMonitorException ex) {
// We don't want calling methods to have to check for exceptions, so just log it
logger.log(Level.SEVERE, "Error adding timing metric", ex);
}
}
}
/**
* Add the timing metric data to the map.
* @param metric The metric to add. stopTiming() should already have been called.
*/
private void addTimingMetric(TimingMetric metric) throws HealthMonitorException {
// Do as little as possible within the synchronized block to minimize
// blocking with multiple threads.
synchronized(this) {
// There's a small check-then-act situation here where isEnabled
// may have changed before reaching this code. This is fine -
// the map still exists and any extra data added after the monitor
// is disabled will be deleted if the monitor is re-enabled. This
// seems preferable to doing another check on isEnabled within
// the synchronized block.
if(timingInfoMap.containsKey(metric.getName())) {
timingInfoMap.get(metric.getName()).addMetric(metric);
} else {
timingInfoMap.put(metric.getName(), new TimingInfo(metric));
}
}
}
/**
* Time a database query.
* Database queries are hard to test in normal processing because the time
* is so dependent on the size of the tables being queried. We use getImages here
* because every table it queries is the same size (one entry for each image) so
* we a) know the size of the tables and b) can use that table size to do
* normalization.
* @throws HealthMonitorException
*/
private void performDatabaseQuery() throws HealthMonitorException {
try {
SleuthkitCase skCase = Case.getOpenCase().getSleuthkitCase();
TimingMetric metric = EnterpriseHealthMonitor.getTimingMetric("Database: getImages query");
List<Image> images = skCase.getImages();
// Through testing we found that this normalization gives us fairly
// consistent results for different numbers of data sources.
long normalization = images.size();
if (images.isEmpty()) {
normalization += 2;
} else if (images.size() == 1){
normalization += 3;
} else if (images.size() < 10) {
normalization += 5;
} else {
normalization += 7;
}
EnterpriseHealthMonitor.submitNormalizedTimingMetric(metric, normalization);
} catch (NoCurrentCaseException ex) {
// If there's no case open, we just can't do the metrics.
} catch (TskCoreException ex) {
throw new HealthMonitorException("Error running getImages()", ex);
}
}
/**
* Collect metrics at a scheduled time.
* @throws HealthMonitorException
*/
private void gatherTimerBasedMetrics() throws HealthMonitorException {
// Time a database query
performDatabaseQuery();
}
/**
* Write the collected metrics to the database.
* @throws HealthMonitorException
*/
private void writeCurrentStateToDatabase() throws HealthMonitorException {
Map<String, TimingInfo> timingMapCopy;
// Do as little as possible within the synchronized block since it will
// block threads attempting to record metrics.
synchronized(this) {
if(! isEnabled.get()) {
return;
}
// Make a shallow copy of the timing map. The map should be small - one entry
// per metric name.
timingMapCopy = new HashMap<>(timingInfoMap);
timingInfoMap.clear();
}
// Check if there's anything to report (right now we only have the timing map)
if(timingMapCopy.keySet().isEmpty()) {
return;
}
logger.log(Level.INFO, "Writing health monitor metrics to database");
// Write to the database
try (CoordinationService.Lock lock = getSharedDbLock()) {
if(lock == null) {
throw new HealthMonitorException("Error getting database lock");
}
Connection conn = connect();
if(conn == null) {
throw new HealthMonitorException("Error getting database connection");
}
// Add timing metrics to the database
String addTimingInfoSql = "INSERT INTO timing_data (name, host, timestamp, count, average, max, min) VALUES (?, ?, ?, ?, ?, ?, ?)";
try (PreparedStatement statement = conn.prepareStatement(addTimingInfoSql)) {
for(String name:timingMapCopy.keySet()) {
TimingInfo info = timingMapCopy.get(name);
statement.setString(1, name);
statement.setString(2, hostName);
statement.setLong(3, System.currentTimeMillis());
statement.setLong(4, info.getCount());
statement.setDouble(5, info.getAverage());
statement.setDouble(6, info.getMax());
statement.setDouble(7, info.getMin());
statement.execute();
}
} catch (SQLException ex) {
throw new HealthMonitorException("Error saving metric data to database", ex);
} finally {
try {
conn.close();
} catch (SQLException ex) {
logger.log(Level.SEVERE, "Error closing Connection.", ex);
}
}
} catch (CoordinationService.CoordinationServiceException ex) {
throw new HealthMonitorException("Error releasing database lock", ex);
}
}
/**
* Check whether the health monitor database exists.
* Does not check the schema.
* @return true if the database exists, false otherwise
* @throws HealthMonitorException
*/
private boolean databaseExists() throws HealthMonitorException {
try {
// Use the same database settings as the case
CaseDbConnectionInfo db = UserPreferences.getDatabaseConnectionInfo();
Class.forName("org.postgresql.Driver"); //NON-NLS
ResultSet rs = null;
try (Connection connection = DriverManager.getConnection("jdbc:postgresql://" + db.getHost() + ":" + db.getPort() + "/postgres", db.getUserName(), db.getPassword()); //NON-NLS
Statement statement = connection.createStatement();) {
String createCommand = "SELECT 1 AS result FROM pg_database WHERE datname='" + DATABASE_NAME + "'";
rs = statement.executeQuery(createCommand);
if(rs.next()) {
logger.log(Level.INFO, "Existing Enterprise Health Monitor database found");
return true;
}
} finally {
if(rs != null) {
rs.close();
}
}
} catch (UserPreferencesException | ClassNotFoundException | SQLException ex) {
throw new HealthMonitorException("Failed check for health monitor database", ex);
}
return false;
}
/**
* Create a new health monitor database.
* @throws HealthMonitorException
*/
private void createDatabase() throws HealthMonitorException {
try {
// Use the same database settings as the case
CaseDbConnectionInfo db = UserPreferences.getDatabaseConnectionInfo();
Class.forName("org.postgresql.Driver"); //NON-NLS
try (Connection connection = DriverManager.getConnection("jdbc:postgresql://" + db.getHost() + ":" + db.getPort() + "/postgres", db.getUserName(), db.getPassword()); //NON-NLS
Statement statement = connection.createStatement();) {
String createCommand = "CREATE DATABASE \"" + DATABASE_NAME + "\" OWNER \"" + db.getUserName() + "\""; //NON-NLS
statement.execute(createCommand);
}
logger.log(Level.INFO, "Created new health monitor database " + DATABASE_NAME);
} catch (UserPreferencesException | ClassNotFoundException | SQLException ex) {
throw new HealthMonitorException("Failed to delete health monitor database", ex);
}
}
/**
* Setup a connection pool for db connections.
* @throws HealthMonitorException
*/
private void setupConnectionPool() throws HealthMonitorException {
try {
CaseDbConnectionInfo db = UserPreferences.getDatabaseConnectionInfo();
connectionPool = new BasicDataSource();
connectionPool.setDriverClassName("org.postgresql.Driver");
StringBuilder connectionURL = new StringBuilder();
connectionURL.append("jdbc:postgresql://");
connectionURL.append(db.getHost());
connectionURL.append(":");
connectionURL.append(db.getPort());
connectionURL.append("/");
connectionURL.append(DATABASE_NAME);
connectionPool.setUrl(connectionURL.toString());
connectionPool.setUsername(db.getUserName());
connectionPool.setPassword(db.getPassword());
// tweak pool configuration
connectionPool.setInitialSize(3); // start with 3 connections
connectionPool.setMaxIdle(CONN_POOL_SIZE); // max of 10 idle connections
connectionPool.setValidationQuery("SELECT version()");
} catch (UserPreferencesException ex) {
throw new HealthMonitorException("Error loading database configuration", ex);
}
}
/**
* Shut down the connection pool
* @throws HealthMonitorException
*/
private void shutdownConnections() throws HealthMonitorException {
try {
synchronized(this) {
if(connectionPool != null){
connectionPool.close();
connectionPool = null; // force it to be re-created on next connect()
}
}
} catch (SQLException ex) {
throw new HealthMonitorException("Failed to close existing database connections.", ex); // NON-NLS
}
}
/**
* Get a database connection.
* Sets up the connection pool if needed.
* @return The Connection object
* @throws HealthMonitorException
*/
private Connection connect() throws HealthMonitorException {
synchronized (this) {
if (connectionPool == null) {
setupConnectionPool();
}
}
try {
return connectionPool.getConnection();
} catch (SQLException ex) {
throw new HealthMonitorException("Error getting connection from connection pool.", ex); // NON-NLS
}
}
/**
* Test whether the database schema has been initialized.
* We do this by looking for the version number.
* @return True if it has been initialized, false otherwise.
* @throws HealthMonitorException
*/
private boolean databaseIsInitialized() throws HealthMonitorException {
Connection conn = connect();
if(conn == null) {
throw new HealthMonitorException("Error getting database connection");
}
ResultSet resultSet = null;
try (Statement statement = conn.createStatement()) {
resultSet = statement.executeQuery("SELECT value FROM db_info WHERE name='SCHEMA_VERSION'");
return resultSet.next();
} catch (SQLException ex) {
// This likely just means that the db_info table does not exist
return false;
} finally {
if(resultSet != null) {
try {
resultSet.close();
} catch (SQLException ex) {
logger.log(Level.SEVERE, "Error closing result set", ex);
}
}
try {
conn.close();
} catch (SQLException ex) {
logger.log(Level.SEVERE, "Error closing Connection.", ex);
}
}
}
/**
* Get the current schema version
* @return the current schema version
* @throws HealthMonitorException
*/
private CaseDbSchemaVersionNumber getVersion() throws HealthMonitorException {
Connection conn = connect();
if(conn == null) {
throw new HealthMonitorException("Error getting database connection");
}
ResultSet resultSet = null;
try (Statement statement = conn.createStatement()) {
int minorVersion = 0;
int majorVersion = 0;
resultSet = statement.executeQuery("SELECT value FROM db_info WHERE name='SCHEMA_MINOR_VERSION'");
if (resultSet.next()) {
String minorVersionStr = resultSet.getString("value");
try {
minorVersion = Integer.parseInt(minorVersionStr);
} catch (NumberFormatException ex) {
throw new HealthMonitorException("Bad value for schema minor version (" + minorVersionStr + ") - database is corrupt");
}
}
resultSet = statement.executeQuery("SELECT value FROM db_info WHERE name='SCHEMA_VERSION'");
if (resultSet.next()) {
String majorVersionStr = resultSet.getString("value");
try {
majorVersion = Integer.parseInt(majorVersionStr);
} catch (NumberFormatException ex) {
throw new HealthMonitorException("Bad value for schema version (" + majorVersionStr + ") - database is corrupt");
}
}
return new CaseDbSchemaVersionNumber(majorVersion, minorVersion);
} catch (SQLException ex) {
throw new HealthMonitorException("Error initializing database", ex);
} finally {
if(resultSet != null) {
try {
resultSet.close();
} catch (SQLException ex) {
logger.log(Level.SEVERE, "Error closing result set", ex);
}
}
try {
conn.close();
} catch (SQLException ex) {
logger.log(Level.SEVERE, "Error closing Connection.", ex);
}
}
}
/**
* Initialize the database.
* @throws HealthMonitorException
*/
private void initializeDatabaseSchema() throws HealthMonitorException {
Connection conn = connect();
if(conn == null) {
throw new HealthMonitorException("Error getting database connection");
}
try (Statement statement = conn.createStatement()) {
conn.setAutoCommit(false);
String createTimingTable =
"CREATE TABLE IF NOT EXISTS timing_data (" +
"id SERIAL PRIMARY KEY," +
"name text NOT NULL," +
"host text NOT NULL," +
"timestamp bigint NOT NULL," +
"count bigint NOT NULL," +
"average double precision NOT NULL," +
"max double precision NOT NULL," +
"min double precision NOT NULL" +
")";
statement.execute(createTimingTable);
String createDbInfoTable =
"CREATE TABLE IF NOT EXISTS db_info (" +
"id SERIAL PRIMARY KEY NOT NULL," +
"name text NOT NULL," +
"value text NOT NULL" +
")";
statement.execute(createDbInfoTable);
statement.execute("INSERT INTO db_info (name, value) VALUES ('SCHEMA_VERSION', '" + CURRENT_DB_SCHEMA_VERSION.getMajor() + "')");
statement.execute("INSERT INTO db_info (name, value) VALUES ('SCHEMA_MINOR_VERSION', '" + CURRENT_DB_SCHEMA_VERSION.getMinor() + "')");
conn.commit();
} catch (SQLException ex) {
try {
conn.rollback();
} catch (SQLException ex2) {
logger.log(Level.SEVERE, "Rollback error");
}
throw new HealthMonitorException("Error initializing database", ex);
} finally {
try {
conn.close();
} catch (SQLException ex) {
logger.log(Level.SEVERE, "Error closing connection.", ex);
}
}
}
/**
* The task called by the ScheduledThreadPoolExecutor to handle
* the database writes.
*/
static final class DatabaseWriteTask implements Runnable {
/**
* Write current metric data to the database
*/
@Override
public void run() {
try {
getInstance().gatherTimerBasedMetrics();
getInstance().writeCurrentStateToDatabase();
} catch (HealthMonitorException ex) {
logger.log(Level.SEVERE, "Error writing current metrics to database", ex); //NON-NLS
}
}
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
switch (Case.Events.valueOf(evt.getPropertyName())) {
case CURRENT_CASE:
if ((null == evt.getNewValue()) && (evt.getOldValue() instanceof Case)) {
// When a case is closed, write the current metrics to the database
healthMonitorExecutor.submit(new EnterpriseHealthMonitor.DatabaseWriteTask());
}
break;
}
}
/**
* Get an exclusive lock for the health monitor database.
* Acquire this before creating, initializing, or updating the database schema.
* @return The lock
* @throws HealthMonitorException
*/
private CoordinationService.Lock getExclusiveDbLock() throws HealthMonitorException{
try {
CoordinationService.Lock lock = CoordinationService.getInstance().tryGetExclusiveLock(CoordinationService.CategoryNode.HEALTH_MONITOR, DATABASE_NAME, 5, TimeUnit.MINUTES);
if(lock != null){
return lock;
}
throw new HealthMonitorException("Error acquiring database lock");
} catch (InterruptedException | CoordinationService.CoordinationServiceException ex){
throw new HealthMonitorException("Error acquiring database lock", ex);
}
}
/**
* Get an shared lock for the health monitor database.
* Acquire this before database reads or writes.
* @return The lock
* @throws HealthMonitorException
*/
private CoordinationService.Lock getSharedDbLock() throws HealthMonitorException{
try {
String databaseNodeName = DATABASE_NAME;
CoordinationService.Lock lock = CoordinationService.getInstance().tryGetSharedLock(CoordinationService.CategoryNode.HEALTH_MONITOR, databaseNodeName, 5, TimeUnit.MINUTES);
if(lock != null){
return lock;
}
throw new HealthMonitorException("Error acquiring database lock");
} catch (InterruptedException | CoordinationService.CoordinationServiceException ex){
throw new HealthMonitorException("Error acquiring database lock");
}
}
/**
* Internal class for collecting timing metrics.
* Instead of storing each TimingMetric, we only store the min and max
* seen and the number of metrics and total duration to compute the average
* later.
* One TimingInfo instance should be created per metric name, and
* additional timing metrics will be added to it.
*/
private class TimingInfo {
private long count; // Number of metrics collected
private double sum; // Sum of the durations collected (nanoseconds)
private double max; // Maximum value found (nanoseconds)
private double min; // Minimum value found (nanoseconds)
TimingInfo(TimingMetric metric) throws HealthMonitorException {
count = 1;
sum = metric.getDuration();
max = metric.getDuration();
min = metric.getDuration();
}
/**
* Add a new TimingMetric to an existing TimingInfo object.
* This is called in a synchronized block for almost all new
* TimingMetric objects, so do as little processing here as possible.
* @param metric The new metric
* @throws HealthMonitorException Will be thrown if the metric hasn't been stopped
*/
void addMetric(TimingMetric metric) throws HealthMonitorException {
// Keep track of needed info to calculate the average
count++;
sum += metric.getDuration();
// Check if this is the longest duration seen
if(max < metric.getDuration()) {
max = metric.getDuration();
}
// Check if this is the lowest duration seen
if(min > metric.getDuration()) {
min = metric.getDuration();
}
}
/**
* Get the average duration
* @return average duration (milliseconds)
*/
double getAverage() {
return sum / count;
}
/**
* Get the maximum duration
* @return maximum duration (milliseconds)
*/
double getMax() {
return max;
}
/**
* Get the minimum duration
* @return minimum duration (milliseconds)
*/
double getMin() {
return min;
}
/**
* Get the total number of metrics collected
* @return number of metrics collected
*/
long getCount() {
return count;
}
}
}

View File

@ -0,0 +1,34 @@
/*
* 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.healthmonitor;
/**
* Exception used internally by the Services Health Monitor
*/
class HealthMonitorException extends Exception {
private static final long serialVersionUID = 1L;
HealthMonitorException(String message) {
super(message);
}
HealthMonitorException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -0,0 +1,53 @@
/*
* 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.healthmonitor;
import java.util.logging.Level;
import org.openide.modules.ModuleInstall;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
public class Installer extends ModuleInstall {
private static final Logger logger = Logger.getLogger(Installer.class.getName());
private static final long serialVersionUID = 1L;
private static Installer instance;
public synchronized static Installer getDefault() {
if (instance == null) {
instance = new Installer();
}
return instance;
}
private Installer() {
super();
}
@Override
public void restored() {
try {
EnterpriseHealthMonitor.startUpIfEnabled();
} catch (HealthMonitorException ex) {
logger.log(Level.SEVERE, "Error starting health services monitor", ex);
}
}
}

View File

@ -0,0 +1,84 @@
/*
* 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.healthmonitor;
/**
* Used to calculate and report timing metrics.
*/
public class TimingMetric {
private final String name;
private final long startingTimestamp;
private Double duration;
TimingMetric(String name) {
this.name = name;
this.startingTimestamp = System.nanoTime();
this.duration = null;
}
/**
* Record how long the metric was running.
*/
void stopTiming() {
long endingTimestamp = System.nanoTime();
this.duration = (double)(endingTimestamp - startingTimestamp) / 1000000;
}
/**
* Get the name of metric
* @return name
*/
String getName() {
return name;
}
/**
* Get the duration of the metric. Will throw an exception if the
* metric has not been stopped.
* @return how long the metric was running (milliseconds)
* @throws HealthMonitorException
*/
double getDuration() throws HealthMonitorException {
if (duration != null) {
return duration;
} else {
throw new HealthMonitorException("getDuration() called before stopTiming()");
}
}
/**
* Normalize the metric by dividing the time by the given counter.
* If the counter is zero, it will be treated the same way as if the
* counter were one.
* @param count Value to divide the duration by
* @throws HealthMonitorException
*/
void normalize(long count) throws HealthMonitorException {
if (duration != null) {
if(count < 0) {
throw new HealthMonitorException("normalize() called with negative count (" + count + ")");
} else if(count > 1) {
duration = duration / count;
} // If count is 0 or 1, do nothing
} else {
throw new HealthMonitorException("normalize() called before stopTiming()");
}
}
}

View File

@ -23,6 +23,12 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.logging.Level;
import org.apache.tika.exception.EncryptedDocumentException;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.sax.BodyContentHandler;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
@ -41,9 +47,11 @@ import org.sleuthkit.datamodel.ReadContentInputStream;
import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
/**
* File ingest module to detect encryption.
* File ingest module to detect encryption and password protection.
*/
final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter {
@ -73,9 +81,10 @@ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter
/**
* Create a EncryptionDetectionFileIngestModule object that will detect
* files that are encrypted and create blackboard artifacts as appropriate.
* The supplied EncryptionDetectionIngestJobSettings object is used to
* configure the module.
* files that are either encrypted or password protected and create
* blackboard artifacts as appropriate. The supplied
* EncryptionDetectionIngestJobSettings object is used to configure the
* module.
*/
EncryptionDetectionFileIngestModule(EncryptionDetectionIngestJobSettings settings) {
minimumEntropy = settings.getMinimumEntropy();
@ -101,13 +110,37 @@ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter
public IngestModule.ProcessResult process(AbstractFile file) {
try {
if (isFileEncrypted(file)) {
return flagFile(file);
/*
* Qualify the file type.
*/
if (!file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)
&& !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS)
&& !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR)
&& !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL_DIR)
&& (!file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK) || slackFilesAllowed)) {
/*
* Qualify the file against hash databases.
*/
if (!file.getKnown().equals(TskData.FileKnown.KNOWN)) {
/*
* Qualify the MIME type.
*/
String mimeType = fileTypeDetector.getMIMEType(file);
if (mimeType.equals("application/octet-stream")) {
if (isFileEncryptionSuspected(file)) {
return flagFile(file, BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_SUSPECTED);
}
} else {
if (isFilePasswordProtected(file)) {
return flagFile(file, BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED);
}
}
}
}
} catch (ReadContentInputStreamException ex) {
} catch (ReadContentInputStreamException | SAXException | TikaException ex) {
logger.log(Level.WARNING, String.format("Unable to read file '%s'", file.getParentPath() + file.getName()), ex);
return IngestModule.ProcessResult.ERROR;
} catch (IOException | TskCoreException ex) {
} catch (IOException ex) {
logger.log(Level.SEVERE, String.format("Unable to process file '%s'", file.getParentPath() + file.getName()), ex);
return IngestModule.ProcessResult.ERROR;
}
@ -138,14 +171,15 @@ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter
/**
* Create a blackboard artifact.
*
* @param The file to be processed.
* @param file The file to be processed.
* @param artifactType The type of artifact to create.
*
* @return 'OK' if the file was processed successfully, or 'ERROR' if there
* was a problem.
*/
private IngestModule.ProcessResult flagFile(AbstractFile file) {
private IngestModule.ProcessResult flagFile(AbstractFile file, BlackboardArtifact.ARTIFACT_TYPE artifactType) {
try {
BlackboardArtifact artifact = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_SUSPECTED);
BlackboardArtifact artifact = file.newArtifact(artifactType);
try {
/*
@ -159,17 +193,19 @@ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter
/*
* Send an event to update the view with the new result.
*/
services.fireModuleDataEvent(new ModuleDataEvent(EncryptionDetectionModuleFactory.getModuleName(), BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_SUSPECTED, Collections.singletonList(artifact)));
services.fireModuleDataEvent(new ModuleDataEvent(EncryptionDetectionModuleFactory.getModuleName(), artifactType, Collections.singletonList(artifact)));
/*
* Make an ingest inbox message.
*/
StringBuilder detailsSb = new StringBuilder();
detailsSb.append("File: ").append(file.getParentPath()).append(file.getName()).append("<br/>\n");
detailsSb.append("Entropy: ").append(calculatedEntropy);
detailsSb.append("File: ").append(file.getParentPath()).append(file.getName());
if (artifactType.equals(BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_SUSPECTED)) {
detailsSb.append("<br/>\n").append("Entropy: ").append(calculatedEntropy);
}
services.postMessage(IngestMessage.createDataMessage(EncryptionDetectionModuleFactory.getModuleName(),
"Encryption Detected Match: " + file.getName(),
artifactType.getDisplayName() + " Match: " + file.getName(),
detailsSb.toString(),
file.getName(),
artifact));
@ -182,16 +218,86 @@ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter
}
/**
* This method checks if the AbstractFile input is encrypted. Initial
* qualifications require that it be an actual file that is not known, meets
* file size requirements, and has a MIME type of
* 'application/octet-stream'.
* This method checks if the AbstractFile input is password protected.
*
* @param file AbstractFile to be checked.
*
* @return True if the AbstractFile is encrypted.
* @return True if the file is password protected.
*
* @throws ReadContentInputStreamException If there is a failure reading
* from the InputStream.
* @throws IOException If there is a failure closing or
* reading from the InputStream.
* @throws SAXException If there was an issue parsing the
* file with Tika.
* @throws TikaException If there was an issue parsing the
* file with Tika.
*/
private boolean isFileEncrypted(AbstractFile file) throws ReadContentInputStreamException, IOException, TskCoreException {
private boolean isFilePasswordProtected(AbstractFile file) throws ReadContentInputStreamException, IOException, SAXException, TikaException {
boolean passwordProtected = false;
switch (file.getMIMEType()) {
case "application/x-ooxml-protected":
/*
* Office Open XML files that are password protected can be
* determined so simply by checking the MIME type.
*/
passwordProtected = true;
break;
case "application/msword":
case "application/vnd.ms-excel":
case "application/vnd.ms-powerpoint":
/*
* A file of one of these types will be determined to be
* password protected or not by attempting to parse it via Tika.
*/
InputStream in = null;
BufferedInputStream bin = null;
try {
in = new ReadContentInputStream(file);
bin = new BufferedInputStream(in);
ContentHandler handler = new BodyContentHandler(-1);
Metadata metadata = new Metadata();
metadata.add(Metadata.RESOURCE_NAME_KEY, file.getName());
AutoDetectParser parser = new AutoDetectParser();
parser.parse(bin, handler, metadata, new ParseContext());
} catch (EncryptedDocumentException ex) {
/*
* Office OLE2 file is determined to be password protected.
*/
passwordProtected = true;
} finally {
if (in != null) {
in.close();
}
if (bin != null) {
bin.close();
}
}
}
return passwordProtected;
}
/**
* This method checks if the AbstractFile input is encrypted. It must meet
* file size requirements before its entropy is calculated. If the entropy
* result meets the minimum entropy value set, the file will be considered
* to be possibly encrypted.
*
* @param file AbstractFile to be checked.
*
* @return True if encryption is suspected.
*
* @throws ReadContentInputStreamException If there is a failure reading
* from the InputStream.
* @throws IOException If there is a failure closing or
* reading from the InputStream.
*/
private boolean isFileEncryptionSuspected(AbstractFile file) throws ReadContentInputStreamException, IOException {
/*
* Criteria for the checks in this method are partially based on
* http://www.forensicswiki.org/wiki/TrueCrypt#Detection
@ -200,55 +306,36 @@ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter
boolean possiblyEncrypted = false;
/*
* Qualify the file type.
* Qualify the size.
*/
if (!file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)
&& !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS)
&& !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR)
&& !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL_DIR)
&& (!file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK) || slackFilesAllowed)) {
/*
* Qualify the file against hash databases.
*/
if (!file.getKnown().equals(TskData.FileKnown.KNOWN)) {
long contentSize = file.getSize();
if (contentSize >= minimumFileSize) {
if (!fileSizeMultipleEnforced || (contentSize % FILE_SIZE_MODULUS) == 0) {
/*
* Qualify the size.
* Qualify the entropy.
*/
long contentSize = file.getSize();
if (contentSize >= minimumFileSize) {
if (!fileSizeMultipleEnforced || (contentSize % FILE_SIZE_MODULUS) == 0) {
/*
* Qualify the MIME type.
*/
String mimeType = fileTypeDetector.getMIMEType(file);
if (mimeType.equals("application/octet-stream")) {
possiblyEncrypted = true;
}
}
calculatedEntropy = calculateEntropy(file);
if (calculatedEntropy >= minimumEntropy) {
possiblyEncrypted = true;
}
}
}
if (possiblyEncrypted) {
calculatedEntropy = calculateEntropy(file);
if (calculatedEntropy >= minimumEntropy) {
return true;
}
}
return false;
return possiblyEncrypted;
}
/**
* Calculate the entropy of the file. The result is used to qualify the file
* as an encrypted file.
* as possibly encrypted.
*
* @param file The file to be calculated against.
*
* @return The entropy of the file.
*
* @throws IOException If there is a failure closing or reading from the
* InputStream.
* @throws ReadContentInputStreamException If there is a failure reading
* from the InputStream.
* @throws IOException If there is a failure closing or
* reading from the InputStream.
*/
private double calculateEntropy(AbstractFile file) throws ReadContentInputStreamException, IOException {
/*

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2017 Basis Technology Corp.
* Copyright 2017-2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -30,7 +30,8 @@ import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel;
/**
* A factory that creates file ingest modules that detect encryption.
* A factory that creates file ingest modules that detect encryption and
* password protection.
*/
@ServiceProvider(service = IngestModuleFactory.class)
@Messages({

View File

@ -33,6 +33,8 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.healthmonitor.EnterpriseHealthMonitor;
import org.sleuthkit.autopsy.healthmonitor.TimingMetric;
import org.sleuthkit.autopsy.ingest.FileIngestModule;
import org.sleuthkit.autopsy.ingest.IngestMessage;
import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
@ -182,8 +184,20 @@ public class HashDbIngestModule implements FileIngestModule {
String md5Hash = file.getMd5Hash();
if (md5Hash == null || md5Hash.isEmpty()) {
try {
TimingMetric metric = EnterpriseHealthMonitor.getTimingMetric("Disk Reads: Hash calculation");
long calcstart = System.currentTimeMillis();
md5Hash = HashUtility.calculateMd5Hash(file);
if (file.getSize() > 0) {
// Surprisingly, the hash calculation does not seem to be correlated that
// strongly with file size until the files get large.
// Only normalize if the file size is greater than ~1MB.
if (file.getSize() < 1000000) {
EnterpriseHealthMonitor.submitTimingMetric(metric);
} else {
// In testing, this normalization gave reasonable resuls
EnterpriseHealthMonitor.submitNormalizedTimingMetric(metric, file.getSize() / 500000);
}
}
file.setMd5Hash(md5Hash);
long delta = (System.currentTimeMillis() - calcstart);
totals.totalCalctime.addAndGet(delta);

View File

@ -82,11 +82,11 @@ public class EventNode extends DisplayableItemNode {
"NodeProperty.displayName.known=Known",
"NodeProperty.displayName.dateTime=Date/Time"})
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set properties = s.get(Sheet.PROPERTIES);
Sheet sheet = super.createSheet();
Sheet.Set properties = sheet.get(Sheet.PROPERTIES);
if (properties == null) {
properties = Sheet.createPropertiesSet();
s.put(properties);
sheet.put(properties);
}
properties.put(new NodeProperty<>("icon", Bundle.NodeProperty_displayName_icon(), "icon", true)); // NON-NLS //gets overridden with icon
@ -96,7 +96,7 @@ public class EventNode extends DisplayableItemNode {
properties.put(new NodeProperty<>("eventSubType", Bundle.NodeProperty_displayName_subType(), "sub type", event.getEventType().getDisplayName())); // NON-NLS
properties.put(new NodeProperty<>("Known", Bundle.NodeProperty_displayName_known(), "known", event.getKnown().toString())); // NON-NLS
return s;
return sheet;
}
/**

View File

@ -60,7 +60,7 @@ public class EventRootNode extends DisplayableItemNode {
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return null;
}

View File

@ -0,0 +1,129 @@
/*
* 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.ingest;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import static junit.framework.Assert.assertEquals;
import junit.framework.Test;
import org.netbeans.junit.NbModuleSuite;
import org.netbeans.junit.NbTestCase;
import org.openide.util.Exceptions;
import org.python.icu.impl.Assert;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.ImageDSProcessor;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.ingest.IngestJobSettings.IngestType;
import org.sleuthkit.autopsy.modules.embeddedfileextractor.EmbeddedFileExtractorModuleFactory;
import org.sleuthkit.autopsy.modules.hashdatabase.HashLookupModuleFactory;
import org.sleuthkit.autopsy.testutils.CaseUtils;
import org.sleuthkit.autopsy.testutils.IngestUtils;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.TskCoreException;
public class EmbeddedFileTest extends NbTestCase {
private static final Path CASE_DIRECTORY_PATH = Paths.get(System.getProperty("java.io.tmpdir"), "EmbeddedFileTest");
private final Path IMAGE_PATH = Paths.get(this.getDataDir().toString(),"embedded.vhd");
public static final String HASH_VALUE = "098f6bcd4621d373cade4e832627b4f6";
private static final int DEEP_FOLDER_COUNT = 25;
private Case openCase;
public static Test suite() {
NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(EmbeddedFileTest.class).
clusters(".*").
enableModules(".*");
return conf.suite();
}
public EmbeddedFileTest(String name) {
super(name);
}
@Override
public void setUp() {
CaseUtils.createCase(CASE_DIRECTORY_PATH);
ImageDSProcessor dataSourceProcessor = new ImageDSProcessor();
IngestUtils.addDataSource(dataSourceProcessor, IMAGE_PATH);
try {
openCase = Case.getOpenCase();
} catch (NoCurrentCaseException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
IngestModuleTemplate embeddedTemplate = IngestUtils.getIngestModuleTemplate(new EmbeddedFileExtractorModuleFactory());
IngestModuleTemplate hashLookupTemplate = IngestUtils.getIngestModuleTemplate(new HashLookupModuleFactory());
ArrayList<IngestModuleTemplate> templates = new ArrayList<>();
templates.add(embeddedTemplate);
templates.add(hashLookupTemplate);
IngestJobSettings ingestJobSettings = new IngestJobSettings(EmbeddedFileTest.class.getCanonicalName(), IngestType.FILES_ONLY, templates);
try {
IngestUtils.runIngestJob(openCase.getDataSources(), ingestJobSettings);
} catch (TskCoreException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
@Override
public void tearDown() {
CaseUtils.closeCase();
CaseUtils.deleteCaseDir(CASE_DIRECTORY_PATH);
}
public void testEncryption() {
try {
List<AbstractFile> results = openCase.getSleuthkitCase().findAllFilesWhere("name LIKE '%%'");
String protectedName1 = "password_protected.zip";
String protectedName2 = "level1_protected.zip";
String protectedName3 = "42.zip";
assertEquals(2207, results.size());
int passwdProtectedZips = 0;
for (AbstractFile file : results) {
//.zip file has artifact TSK_ENCRYPTION_DETECTED
if (file.getName().equalsIgnoreCase(protectedName1) || file.getName().equalsIgnoreCase(protectedName2) || file.getName().equalsIgnoreCase(protectedName3)){
ArrayList<BlackboardArtifact> artifacts = file.getAllArtifacts();
assertEquals(1, artifacts.size());
for (BlackboardArtifact artifact : artifacts) {
assertEquals(artifact.getArtifactTypeID(), BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED.getTypeID());
passwdProtectedZips++;
}
} else {//No other files have artifact defined
assertEquals(0, file.getAllArtifacts().size());
}
}
//Make sure 3 password protected zip files have been tested: password_protected.zip, level1_protected.zip and 42.zip that we download for bomb testing.
assertEquals(3, passwdProtectedZips);
} catch (TskCoreException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
}

View File

@ -18,20 +18,14 @@
*/
package org.sleuthkit.autopsy.ingest;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import static junit.framework.Assert.assertFalse;
import org.netbeans.junit.NbModuleSuite;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.casemodule.CaseDetails;
import junit.framework.Test;
import org.apache.commons.io.FileUtils;
import org.netbeans.junit.NbTestCase;
import org.openide.util.Exceptions;
import org.python.icu.impl.Assert;
@ -39,7 +33,6 @@ import org.sleuthkit.autopsy.casemodule.ImageDSProcessor;
import org.sleuthkit.autopsy.casemodule.LocalFilesDSProcessor;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.casemodule.services.FileManager;
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
import org.sleuthkit.autopsy.ingest.IngestJobSettings.IngestType;
import org.sleuthkit.autopsy.modules.embeddedfileextractor.EmbeddedFileExtractorModuleFactory;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeIdModuleFactory;
@ -50,11 +43,10 @@ import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.FullNameCond
import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.MetaTypeCondition;
import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.ParentPathCondition;
import org.sleuthkit.autopsy.modules.photoreccarver.PhotoRecCarverIngestModuleFactory;
import org.sleuthkit.autopsy.testutils.DataSourceProcessorRunner;
import org.sleuthkit.autopsy.testutils.DataSourceProcessorRunner.ProcessorCallback;
import org.sleuthkit.autopsy.testutils.CaseUtils;
import org.sleuthkit.autopsy.testutils.IngestJobRunner;
import org.sleuthkit.autopsy.testutils.IngestUtils;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
@ -77,26 +69,14 @@ public class IngestFileFiltersTest extends NbTestCase {
@Override
public void tearDown() {
try {
Case.closeCurrentCase();
//Seems like we need some time to close the case.
try {
Thread.sleep(2000);
} catch (Exception ex) {
}
assertFalse(Case.isCaseOpen());
} catch (CaseActionException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
CaseUtils.closeCase();
}
public void testBasicDir() {
Path casePath = Paths.get(System.getProperty("java.io.tmpdir"), "testBasicDir");
createCase(casePath);
CaseUtils.createCase(casePath);
ImageDSProcessor dataSourceProcessor = new ImageDSProcessor();
addDataSourceToCase(dataSourceProcessor, IMAGE_PATH);
IngestUtils.addDataSource(dataSourceProcessor, IMAGE_PATH);
HashMap<String, Rule> rule = new HashMap<>();
rule.put("Rule", new Rule("testFileType", null, new MetaTypeCondition(MetaTypeCondition.Type.FILES), new ParentPathCondition("dir1"), null, null, null));
@ -106,8 +86,9 @@ public class IngestFileFiltersTest extends NbTestCase {
try {
Case openCase = Case.getOpenCase();
ArrayList<IngestModuleTemplate> templates = new ArrayList<>();
templates.add(getIngestModuleTemplate(new FileTypeIdModuleFactory()));
runIngestJob(openCase.getDataSources(), templates, dirFilter);
templates.add(IngestUtils.getIngestModuleTemplate(new FileTypeIdModuleFactory()));
IngestJobSettings ingestJobSettings = new IngestJobSettings(IngestFileFiltersTest.class.getCanonicalName(), IngestJobSettings.IngestType.FILES_ONLY, templates, dirFilter);
IngestUtils.runIngestJob(openCase.getDataSources(), ingestJobSettings);
FileManager fileManager = openCase.getServices().getFileManager();
List<AbstractFile> results = fileManager.findFiles("file.jpg", "dir1");
String mimeType = results.get(0).getMIMEType();
@ -136,9 +117,9 @@ public class IngestFileFiltersTest extends NbTestCase {
public void testExtAndDirWithOneRule() {
Path casePath = Paths.get(System.getProperty("java.io.tmpdir"), "testExtAndDirWithOneRule");
createCase(casePath);
CaseUtils.createCase(casePath);
ImageDSProcessor dataSourceProcessor = new ImageDSProcessor();
addDataSourceToCase(dataSourceProcessor, IMAGE_PATH);
IngestUtils.addDataSource(dataSourceProcessor, IMAGE_PATH);
HashMap<String, Rule> rules = new HashMap<>();
rules.put("Rule", new Rule("testExtAndDirWithOneRule", new ExtensionCondition("jpg"), new MetaTypeCondition(MetaTypeCondition.Type.FILES), new ParentPathCondition("dir1"), null, null, null));
@ -148,8 +129,9 @@ public class IngestFileFiltersTest extends NbTestCase {
try {
Case openCase = Case.getOpenCase();
ArrayList<IngestModuleTemplate> templates = new ArrayList<>();
templates.add(getIngestModuleTemplate(new FileTypeIdModuleFactory()));
runIngestJob(openCase.getDataSources(), templates, filesExtDirsFilter);
templates.add(IngestUtils.getIngestModuleTemplate(new FileTypeIdModuleFactory()));
IngestJobSettings ingestJobSettings = new IngestJobSettings(IngestFileFiltersTest.class.getCanonicalName(), IngestJobSettings.IngestType.FILES_ONLY, templates, filesExtDirsFilter);
IngestUtils.runIngestJob(openCase.getDataSources(), ingestJobSettings);
FileManager fileManager = Case.getOpenCase().getServices().getFileManager();
List<AbstractFile> results = fileManager.findFiles("%%");
assertEquals(62, results.size());
@ -171,9 +153,9 @@ public class IngestFileFiltersTest extends NbTestCase {
public void testExtAndDirWithTwoRules() {
Path casePath = Paths.get(System.getProperty("java.io.tmpdir"), "testExtAndDirWithTwoRules");
createCase(casePath);
CaseUtils.createCase(casePath);
ImageDSProcessor dataSourceProcessor = new ImageDSProcessor();
addDataSourceToCase(dataSourceProcessor, IMAGE_PATH);
IngestUtils.addDataSource(dataSourceProcessor, IMAGE_PATH);
HashMap<String, Rule> rules = new HashMap<>();
rules.put("rule1", new Rule("FindJpgExtention", new ExtensionCondition("jpg"), new MetaTypeCondition(MetaTypeCondition.Type.FILES), null, null, null, null));
@ -184,8 +166,9 @@ public class IngestFileFiltersTest extends NbTestCase {
try {
Case openCase = Case.getOpenCase();
ArrayList<IngestModuleTemplate> templates = new ArrayList<>();
templates.add(getIngestModuleTemplate(new FileTypeIdModuleFactory()));
runIngestJob(openCase.getDataSources(), templates, filesExtDirsFilter);
templates.add(IngestUtils.getIngestModuleTemplate(new FileTypeIdModuleFactory()));
IngestJobSettings ingestJobSettings = new IngestJobSettings(IngestFileFiltersTest.class.getCanonicalName(), IngestJobSettings.IngestType.FILES_ONLY, templates, filesExtDirsFilter);
IngestUtils.runIngestJob(openCase.getDataSources(), ingestJobSettings);
FileManager fileManager = Case.getOpenCase().getServices().getFileManager();
List<AbstractFile> results = fileManager.findFiles("%%");
assertEquals(62, results.size());
@ -215,9 +198,9 @@ public class IngestFileFiltersTest extends NbTestCase {
public void testFullFileNameRule() {
Path casePath = Paths.get(System.getProperty("java.io.tmpdir"), "testFullFileNameRule");
createCase(casePath);
CaseUtils.createCase(casePath);
ImageDSProcessor dataSourceProcessor = new ImageDSProcessor();
addDataSourceToCase(dataSourceProcessor, IMAGE_PATH);
IngestUtils.addDataSource(dataSourceProcessor, IMAGE_PATH);
HashMap<String, Rule> rules = new HashMap<>();
rules.put("rule", new Rule("FindFileWithFullName", new FullNameCondition("file.docx"), new MetaTypeCondition(MetaTypeCondition.Type.FILES), null, null, null, null));
@ -227,9 +210,9 @@ public class IngestFileFiltersTest extends NbTestCase {
try {
Case openCase = Case.getOpenCase();
ArrayList<IngestModuleTemplate> templates = new ArrayList<>();
templates.add(getIngestModuleTemplate(new FileTypeIdModuleFactory()));
runIngestJob(openCase.getDataSources(), templates, fullNameFilter);
templates.add(IngestUtils.getIngestModuleTemplate(new FileTypeIdModuleFactory()));
IngestJobSettings ingestJobSettings = new IngestJobSettings(IngestFileFiltersTest.class.getCanonicalName(), IngestJobSettings.IngestType.FILES_ONLY, templates, fullNameFilter);
IngestUtils.runIngestJob(openCase.getDataSources(), ingestJobSettings);
FileManager fileManager = Case.getOpenCase().getServices().getFileManager();
List<AbstractFile> results = fileManager.findFiles("%%");
assertEquals(62, results.size());
@ -251,9 +234,9 @@ public class IngestFileFiltersTest extends NbTestCase {
public void testCarvingWithExtRuleAndUnallocSpace() {
Path casePath = Paths.get(System.getProperty("java.io.tmpdir"), "testCarvingWithExtRuleAndUnallocSpace");
createCase(casePath);
CaseUtils.createCase(casePath);
ImageDSProcessor dataSourceProcessor = new ImageDSProcessor();
addDataSourceToCase(dataSourceProcessor, IMAGE_PATH);
IngestUtils.addDataSource(dataSourceProcessor, IMAGE_PATH);
HashMap<String, Rule> rules = new HashMap<>();
rules.put("rule1", new Rule("FindJpgExtention", new ExtensionCondition("jpg"), new MetaTypeCondition(MetaTypeCondition.Type.FILES), null, null, null, null));
@ -265,9 +248,10 @@ public class IngestFileFiltersTest extends NbTestCase {
try {
Case openCase = Case.getOpenCase();
ArrayList<IngestModuleTemplate> templates = new ArrayList<>();
templates.add(getIngestModuleTemplate(new FileTypeIdModuleFactory()));
templates.add(getIngestModuleTemplate(new PhotoRecCarverIngestModuleFactory()));
runIngestJob(openCase.getDataSources(), templates, extensionFilter);
templates.add(IngestUtils.getIngestModuleTemplate(new FileTypeIdModuleFactory()));
templates.add(IngestUtils.getIngestModuleTemplate(new PhotoRecCarverIngestModuleFactory()));
IngestJobSettings ingestJobSettings = new IngestJobSettings(IngestFileFiltersTest.class.getCanonicalName(), IngestJobSettings.IngestType.FILES_ONLY, templates, extensionFilter);
IngestUtils.runIngestJob(openCase.getDataSources(), ingestJobSettings);
FileManager fileManager = Case.getOpenCase().getServices().getFileManager();
List<AbstractFile> results = fileManager.findFiles("%%");
assertEquals(70, results.size());
@ -299,9 +283,9 @@ public class IngestFileFiltersTest extends NbTestCase {
public void testCarvingNoUnallocatedSpace() {
Path casePath = Paths.get(System.getProperty("java.io.tmpdir"), "testCarvingNoUnallocatedSpace");
createCase(casePath);
CaseUtils.createCase(casePath);
ImageDSProcessor dataSourceProcessor = new ImageDSProcessor();
addDataSourceToCase(dataSourceProcessor, IMAGE_PATH);
IngestUtils.addDataSource(dataSourceProcessor, IMAGE_PATH);
HashMap<String, Rule> rules = new HashMap<>();
rules.put("rule1", new Rule("FindJpgExtention", new ExtensionCondition("jpg"), new MetaTypeCondition(MetaTypeCondition.Type.FILES), null, null, null, null));
@ -313,8 +297,8 @@ public class IngestFileFiltersTest extends NbTestCase {
try {
Case openCase = Case.getOpenCase();
ArrayList<IngestModuleTemplate> templates = new ArrayList<>();
templates.add(getIngestModuleTemplate(new FileTypeIdModuleFactory()));
templates.add(getIngestModuleTemplate(new PhotoRecCarverIngestModuleFactory()));
templates.add(IngestUtils.getIngestModuleTemplate(new FileTypeIdModuleFactory()));
templates.add(IngestUtils.getIngestModuleTemplate(new PhotoRecCarverIngestModuleFactory()));
IngestJobSettings ingestJobSettings = new IngestJobSettings(IngestFileFiltersTest.class.getCanonicalName(), IngestType.FILES_ONLY, templates, extensionFilter);
try {
List<IngestModuleError> errs = IngestJobRunner.runIngestJob(openCase.getDataSources(), ingestJobSettings);
@ -333,9 +317,9 @@ public class IngestFileFiltersTest extends NbTestCase {
public void testEmbeddedModule() {
Path casePath = Paths.get(System.getProperty("java.io.tmpdir"), "testEmbeddedModule");
createCase(casePath);
CaseUtils.createCase(casePath);
LocalFilesDSProcessor dataSourceProcessor = new LocalFilesDSProcessor();
addDataSourceToCase(dataSourceProcessor, ZIPFILE_PATH);
IngestUtils.addDataSource(dataSourceProcessor, ZIPFILE_PATH);
//Build the filter to find jpg files
HashMap<String, Rule> rules = new HashMap<>();
@ -348,9 +332,10 @@ public class IngestFileFiltersTest extends NbTestCase {
try {
Case openCase = Case.getOpenCase();
ArrayList<IngestModuleTemplate> templates = new ArrayList<>();
templates.add(getIngestModuleTemplate(new FileTypeIdModuleFactory()));
templates.add(getIngestModuleTemplate(new EmbeddedFileExtractorModuleFactory()));
runIngestJob(openCase.getDataSources(), templates, embeddedFilter);
templates.add(IngestUtils.getIngestModuleTemplate(new FileTypeIdModuleFactory()));
templates.add(IngestUtils.getIngestModuleTemplate(new EmbeddedFileExtractorModuleFactory()));
IngestJobSettings ingestJobSettings = new IngestJobSettings(IngestFileFiltersTest.class.getCanonicalName(), IngestJobSettings.IngestType.FILES_ONLY, templates, embeddedFilter);
IngestUtils.runIngestJob(openCase.getDataSources(), ingestJobSettings);
FileManager fileManager = Case.getOpenCase().getServices().getFileManager();
//get all .jpg files in zip file
List<AbstractFile> results = fileManager.findFiles("%%");
@ -376,64 +361,4 @@ public class IngestFileFiltersTest extends NbTestCase {
Assert.fail(ex);
}
}
private void runIngestJob(List<Content> datasources, ArrayList<IngestModuleTemplate> templates, FilesSet filter) {
IngestJobSettings ingestJobSettings = new IngestJobSettings(IngestFileFiltersTest.class.getCanonicalName(), IngestType.FILES_ONLY, templates, filter);
try {
List<IngestModuleError> errs = IngestJobRunner.runIngestJob(datasources, ingestJobSettings);
for (IngestModuleError err : errs) {
System.out.println(String.format("Error: %s: %s.", err.getModuleDisplayName(), err.toString()));
}
assertEquals(0, errs.size());
} catch (InterruptedException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
private IngestModuleTemplate getIngestModuleTemplate(IngestModuleFactoryAdapter factory) {
IngestModuleIngestJobSettings settings = factory.getDefaultIngestJobSettings();
IngestModuleTemplate template = new IngestModuleTemplate(factory, settings);
template.setEnabled(true);
return template;
}
private void createCase(Path casePath) {
// Delete the test directory, if it exists
if (casePath.toFile().exists()) {
try {
FileUtils.deleteDirectory(casePath.toFile());
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
assertFalse("Unable to delete existing test directory", casePath.toFile().exists());
// Create the test directory
casePath.toFile().mkdirs();
assertTrue("Unable to create test directory", casePath.toFile().exists());
try {
Case.createAsCurrentCase(Case.CaseType.SINGLE_USER_CASE, casePath.toString(), new CaseDetails("IngestFiltersTest"));
} catch (CaseActionException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
assertTrue(casePath.toFile().exists());
}
private void addDataSourceToCase(AutoIngestDataSourceProcessor dataSourceProcessor, Path dataSourcePath) {
try {
ProcessorCallback callBack = DataSourceProcessorRunner.runDataSourceProcessor(dataSourceProcessor, dataSourcePath);
List<Content> dataSourceContent = callBack.getDataSourceContent();
assertEquals(1, dataSourceContent.size());
List<String> errorMessages = callBack.getErrorMessages();
assertEquals(0, errorMessages.size());
} catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException | InterruptedException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
}

View File

@ -0,0 +1,82 @@
/*
* 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.testutils;
import java.io.IOException;
import java.nio.file.Path;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import org.apache.commons.io.FileUtils;
import org.openide.util.Exceptions;
import org.python.icu.impl.Assert;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.casemodule.CaseDetails;
public final class CaseUtils {
private CaseUtils() {
}
public static void createCase(Path caseDirectoryPath) {
//Make sure the test is starting with a clean state. So delete the test directory, if it exists.
deleteCaseDir(caseDirectoryPath);
assertFalse("Unable to delete existing test directory", caseDirectoryPath.toFile().exists());
// Create the test directory
caseDirectoryPath.toFile().mkdirs();
assertTrue("Unable to create test directory", caseDirectoryPath.toFile().exists());
try {
Case.createAsCurrentCase(Case.CaseType.SINGLE_USER_CASE, caseDirectoryPath.toString(), new CaseDetails("IngestFiltersTest"));
} catch (CaseActionException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
assertTrue(caseDirectoryPath.toFile().exists());
}
public static void closeCase() {
try {
Case.closeCurrentCase();
//Seems like we need some time to close the case, so file handler later can delete the case directory.
try {
Thread.sleep(20000);
} catch (Exception ex) {
}
} catch (CaseActionException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
public static void deleteCaseDir(Path caseDirectoryPath) {
if (!caseDirectoryPath.toFile().exists()) {
return;
}
try {
FileUtils.deleteDirectory(caseDirectoryPath.toFile());
} catch (IOException ex) {
//We just want to make sure the case directory doesn't exist when the test starts. It shouldn't cause failure if the case directory couldn't be deleted after a test finished.
System.out.println("INFO: Unable to delete case directory: " + caseDirectoryPath.toString());
}
}
}

View File

@ -0,0 +1,72 @@
/*
* 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.testutils;
import java.nio.file.Path;
import java.util.List;
import static junit.framework.Assert.assertEquals;
import org.openide.util.Exceptions;
import org.python.icu.impl.Assert;
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestModuleError;
import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestModuleTemplate;
import org.sleuthkit.datamodel.Content;
public final class IngestUtils {
private IngestUtils() {
}
public static void addDataSource(AutoIngestDataSourceProcessor dataSourceProcessor, Path dataSourcePath) {
try {
DataSourceProcessorRunner.ProcessorCallback callBack = DataSourceProcessorRunner.runDataSourceProcessor(dataSourceProcessor, dataSourcePath);
List<String> errorMessages = callBack.getErrorMessages();
assertEquals(0, errorMessages.size());
} catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException | InterruptedException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
public static void runIngestJob(List<Content> datasources, IngestJobSettings ingestJobSettings) {
try {
List<IngestModuleError> errs = IngestJobRunner.runIngestJob(datasources, ingestJobSettings);
for (IngestModuleError err : errs) {
System.out.println(String.format("Error: %s: %s.", err.getModuleDisplayName(), err.toString()));
}
assertEquals(0, errs.size());
} catch (InterruptedException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
public static IngestModuleTemplate getIngestModuleTemplate(IngestModuleFactoryAdapter factory) {
IngestModuleIngestJobSettings settings = factory.getDefaultIngestJobSettings();
IngestModuleTemplate template = new IngestModuleTemplate(factory, settings);
template.setEnabled(true);
return template;
}
}

View File

@ -33,6 +33,14 @@
<specification-version>1.49.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.netbeans.swing.outline</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.34.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.awt</code-name-base>
<build-prerequisite/>
@ -49,6 +57,14 @@
<specification-version>7.41.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.explorer</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.62.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.filesystems</code-name-base>
<build-prerequisite/>

View File

@ -0,0 +1,155 @@
/*
* 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.experimental.autoingest;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import org.openide.util.NbBundle;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotDialog;
final class AutoIngestAdminActions {
@NbBundle.Messages({"AutoIngestAdminActions.progressDialogAction.title=Ingest Progress"})
static final class ProgressDialogAction extends AbstractAction {
private static final long serialVersionUID = 1L;
ProgressDialogAction() {
super(Bundle.AutoIngestAdminActions_progressDialogAction_title());
}
@Override
public void actionPerformed(ActionEvent e) {
//TODO JIRA-3734
final AutoIngestDashboardTopComponent tc = (AutoIngestDashboardTopComponent) WindowManager.getDefault().findTopComponent(AutoIngestDashboardTopComponent.PREFERRED_ID);
if (tc != null) {
AutoIngestDashboard dashboard = tc.getAutoIngestDashboard();
if (dashboard != null) {
new IngestProgressSnapshotDialog(dashboard.getTopLevelAncestor(), true);
}
}
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); //To change body of generated methods, choose Tools | Templates.
}
}
@NbBundle.Messages({"AutoIngestAdminActions.cancelJobAction.title=Cancel Job"})
static final class CancelJobAction extends AbstractAction {
private static final long serialVersionUID = 1L;
CancelJobAction() {
super(Bundle.AutoIngestAdminActions_cancelJobAction_title());
}
@Override
public void actionPerformed(ActionEvent e) {
//TODO JIRA-3738
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); //To change body of generated methods, choose Tools | Templates.
}
}
@NbBundle.Messages({"AutoIngestAdminActions.cancelModuleAction.title=Cancel Module"})
static final class CancelModuleAction extends AbstractAction {
private static final long serialVersionUID = 1L;
CancelModuleAction() {
super(Bundle.AutoIngestAdminActions_cancelModuleAction_title());
}
@Override
public void actionPerformed(ActionEvent e) {
//TODO JIRA-3738
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); //To change body of generated methods, choose Tools | Templates.
}
}
@NbBundle.Messages({"AutoIngestAdminActions.reprocessJobAction.title=Reprocess Job"})
static final class ReprocessJobAction extends AbstractAction {
private static final long serialVersionUID = 1L;
ReprocessJobAction() {
super(Bundle.AutoIngestAdminActions_reprocessJobAction_title());
}
@Override
public void actionPerformed(ActionEvent e) {
//TODO JIRA-3739
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); //To change body of generated methods, choose Tools | Templates.
}
}
@NbBundle.Messages({"AutoIngestAdminActions.deleteCaseAction.title=Delete Case"})
static final class DeleteCaseAction extends AbstractAction {
private static final long serialVersionUID = 1L;
DeleteCaseAction() {
super(Bundle.AutoIngestAdminActions_deleteCaseAction_title());
}
@Override
public void actionPerformed(ActionEvent e) {
//TODO JIRA-3740
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); //To change body of generated methods, choose Tools | Templates.
}
}
@NbBundle.Messages({"AutoIngestAdminActions.showCaseLogAction.title=Show Case Log"})
static final class ShowCaseLogAction extends AbstractAction {
private static final long serialVersionUID = 1L;
ShowCaseLogAction() {
super(Bundle.AutoIngestAdminActions_showCaseLogAction_title());
}
@Override
public void actionPerformed(ActionEvent e) {
//TODO JIRA-
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); //To change body of generated methods, choose Tools | Templates.
}
}
}

View File

@ -26,37 +26,29 @@
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="pendingScrollPane" max="32767" attributes="0"/>
<Component id="runningScrollPane" alignment="0" max="32767" attributes="0"/>
<Component id="completedScrollPane" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="lbServicesStatus" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="tbServicesStatusMessage" pref="861" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="1" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="refreshButton" linkSize="1" min="-2" pref="100" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="prioritizeJobButton" linkSize="1" min="-2" pref="100" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="deprioritizeJobButton" min="-2" pref="127" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="prioritizeCaseButton" linkSize="1" min="-2" pref="100" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="deprioritizeCaseButton" min="-2" pref="127" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="clusterMetricsButton" linkSize="1" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="lbPending" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lbCompleted" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lbRunning" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="lbServicesStatus" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="tbServicesStatusMessage" min="-2" pref="861" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="refreshButton" linkSize="1" min="-2" pref="100" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="clusterMetricsButton" linkSize="1" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
@ -65,60 +57,48 @@
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lbServicesStatus" alignment="3" min="-2" pref="23" max="-2" attributes="0"/>
<Component id="tbServicesStatusMessage" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="lbPending" min="-2" pref="23" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
<Component id="pendingScrollPane" min="-2" pref="215" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="pendingScrollPane" max="32767" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="lbRunning" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
<Component id="runningScrollPane" min="-2" pref="133" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="runningScrollPane" pref="133" max="32767" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="lbCompleted" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="completedScrollPane" min="-2" pref="179" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="completedScrollPane" pref="179" max="32767" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="refreshButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="prioritizeJobButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="prioritizeCaseButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="clusterMetricsButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="deprioritizeJobButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="deprioritizeCaseButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="pendingScrollPane">
<Properties>
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
<Property name="verticalScrollBarPolicy" type="int" value="21"/>
<Property name="opaque" type="boolean" value="false"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[2, 215]"/>
</Property>
</Properties>
<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="pendingTable">
<Properties>
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="pendingTableModel" type="code"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestDashboard.pendingTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="rowHeight" type="int" value="20" postCode="pendingTable.setSelectionModel(new DefaultListSelectionModel() {&#xa; private static final long serialVersionUID = 1L;&#xa; @Override&#xa; public void setSelectionInterval(int index0, int index1) {&#xa; if (index0 == pendingTable.getSelectedRow()) {&#xa; pendingTable.clearSelection();&#xa; } else {&#xa; super.setSelectionInterval(index0, index1);&#xa; }&#xa; }&#xa;});"/>
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
<JTableSelectionModel selectionMode="0"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JScrollPane" name="runningScrollPane">
<AuxValues>
@ -126,22 +106,6 @@
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="runningTable">
<Properties>
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="runningTableModel" type="code"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestDashboard.runningTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="rowHeight" type="int" value="20" postCode="runningTable.setSelectionModel(new DefaultListSelectionModel() {&#xa; private static final long serialVersionUID = 1L;&#xa; @Override&#xa; public void setSelectionInterval(int index0, int index1) {&#xa; if (index0 == runningTable.getSelectedRow()) {&#xa; runningTable.clearSelection();&#xa; } else {&#xa; super.setSelectionInterval(index0, index1);&#xa; }&#xa; }&#xa;});"/>
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
<JTableSelectionModel selectionMode="0"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JScrollPane" name="completedScrollPane">
<AuxValues>
@ -149,22 +113,6 @@
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="completedTable">
<Properties>
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="completedTableModel" type="code"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestDashboard.completedTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="rowHeight" type="int" value="20" postCode="completedTable.setSelectionModel(new DefaultListSelectionModel() {&#xa; private static final long serialVersionUID = 1L;&#xa; @Override&#xa; public void setSelectionInterval(int index0, int index1) {&#xa; if (index0 == completedTable.getSelectedRow()) {&#xa; completedTable.clearSelection();&#xa; } else {&#xa; super.setSelectionInterval(index0, index1);&#xa; }&#xa; }&#xa;});"/>
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
<JTableSelectionModel selectionMode="0"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="lbPending">
<Properties>
@ -233,34 +181,6 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="prioritizeJobButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestDashboard.prioritizeJobButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestDashboard.prioritizeJobButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="prioritizeJobButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="prioritizeCaseButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestDashboard.prioritizeCaseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestDashboard.prioritizeCaseButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="prioritizeCaseButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="clusterMetricsButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
@ -271,33 +191,5 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="clusterMetricsButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="deprioritizeJobButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestDashboard.deprioritizeJobButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestDashboard.deprioritizeJobButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deprioritizeJobButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="deprioritizeCaseButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestDashboard.deprioritizeCaseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestDashboard.deprioritizeCaseButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deprioritizeCaseButtonActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Form>

View File

@ -19,38 +19,23 @@
package org.sleuthkit.autopsy.experimental.autoingest;
import java.awt.Cursor;
import java.awt.EventQueue;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Instant;
import java.util.Date;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.logging.Level;
import javax.swing.DefaultListSelectionModel;
import java.awt.Color;
import java.awt.EventQueue;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.event.ListSelectionEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.core.ServicesMonitor;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestMonitor.JobsSnapshot;
import org.sleuthkit.autopsy.guiutils.DurationCellRenderer;
import org.sleuthkit.autopsy.guiutils.LongDateCellRenderer;
import org.sleuthkit.autopsy.guiutils.StatusIconCellRenderer;
/**
* A dashboard for monitoring an automated ingest cluster.
@ -58,35 +43,12 @@ import org.sleuthkit.autopsy.guiutils.StatusIconCellRenderer;
final class AutoIngestDashboard extends JPanel implements Observer {
private static final long serialVersionUID = 1L;
private static final int GENERIC_COL_MIN_WIDTH = 30;
private static final int GENERIC_COL_MAX_WIDTH = 2000;
private static final int PENDING_TABLE_COL_PREFERRED_WIDTH = 280;
private static final int RUNNING_TABLE_COL_PREFERRED_WIDTH = 175;
private static final int PRIORITY_COLUMN_PREFERRED_WIDTH = 60;
private static final int PRIORITY_COLUMN_MAX_WIDTH = 150;
private static final int STAGE_TIME_COL_MIN_WIDTH = 250;
private static final int STAGE_TIME_COL_MAX_WIDTH = 450;
private static final int TIME_COL_MIN_WIDTH = 30;
private static final int TIME_COL_MAX_WIDTH = 250;
private static final int TIME_COL_PREFERRED_WIDTH = 140;
private static final int NAME_COL_MIN_WIDTH = 100;
private static final int NAME_COL_MAX_WIDTH = 250;
private static final int NAME_COL_PREFERRED_WIDTH = 140;
private static final int STAGE_COL_MIN_WIDTH = 70;
private static final int STAGE_COL_MAX_WIDTH = 2000;
private static final int STAGE_COL_PREFERRED_WIDTH = 300;
private static final int STATUS_COL_MIN_WIDTH = 55;
private static final int STATUS_COL_MAX_WIDTH = 250;
private static final int STATUS_COL_PREFERRED_WIDTH = 55;
private static final int COMPLETED_TIME_COL_MIN_WIDTH = 30;
private static final int COMPLETED_TIME_COL_MAX_WIDTH = 2000;
private static final int COMPLETED_TIME_COL_PREFERRED_WIDTH = 280;
private static final Logger LOGGER = Logger.getLogger(AutoIngestDashboard.class.getName());
private final DefaultTableModel pendingTableModel;
private final DefaultTableModel runningTableModel;
private final DefaultTableModel completedTableModel;
private AutoIngestMonitor autoIngestMonitor;
private AutoIngestJobsPanel pendingJobsPanel;
private AutoIngestJobsPanel runningJobsPanel;
private AutoIngestJobsPanel completedJobsPanel;
/**
* Maintain a mapping of each service to it's last status update.
*/
@ -113,38 +75,56 @@ final class AutoIngestDashboard extends JPanel implements Observer {
/**
* Constructs a panel for monitoring an automated ingest cluster.
*/
@Messages({"AutoIngestDashboard.pendingTable.toolTipText=The Pending table displays the order upcoming Jobs will be processed with the top of the list first",
"AutoIngestDashboard.runningTable.toolTipText=The Running table displays the currently running Job and information about it",
"AutoIngestDashboard.completedTable.toolTipText=The Completed table shows all Jobs that have been processed already"})
private AutoIngestDashboard() {
this.statusByService = new ConcurrentHashMap<>();
pendingTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0);
runningTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0);
completedTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0);
initComponents();
statusByService.put(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString(), NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.tbServicesStatusMessage.Message.Down"));
statusByService.put(ServicesMonitor.Service.REMOTE_KEYWORD_SEARCH.toString(), NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.tbServicesStatusMessage.Message.Down"));
statusByService.put(ServicesMonitor.Service.MESSAGING.toString(), NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.tbServicesStatusMessage.Message.Down"));
setServicesStatusMessage();
initPendingJobsTable();
initRunningJobsTable();
initCompletedJobsTable();
pendingJobsPanel = new AutoIngestJobsPanel(AutoIngestJobsNode.AutoIngestJobStatus.PENDING_JOB);
pendingJobsPanel.setSize(pendingScrollPane.getSize());
pendingScrollPane.add(pendingJobsPanel);
pendingScrollPane.setViewportView(pendingJobsPanel);
pendingJobsPanel.setToolTipText(Bundle.AutoIngestDashboard_pendingTable_toolTipText());
runningJobsPanel = new AutoIngestJobsPanel(AutoIngestJobsNode.AutoIngestJobStatus.RUNNING_JOB);
runningJobsPanel.setSize(runningScrollPane.getSize());
runningScrollPane.add(runningJobsPanel);
runningScrollPane.setViewportView(runningJobsPanel);
runningJobsPanel.setToolTipText(Bundle.AutoIngestDashboard_runningTable_toolTipText());
completedJobsPanel = new AutoIngestJobsPanel(AutoIngestJobsNode.AutoIngestJobStatus.COMPLETED_JOB);
completedJobsPanel.setSize(completedScrollPane.getSize());
completedScrollPane.add(completedJobsPanel);
completedScrollPane.setViewportView(completedJobsPanel);
completedJobsPanel.setToolTipText(Bundle.AutoIngestDashboard_completedTable_toolTipText());
/*
* Must set this flag, otherwise pop up menus don't close properly.
*/
UIManager.put("PopupMenu.consumeEventOnClose", false);
}
AutoIngestMonitor getMonitor() {
return autoIngestMonitor;
}
AutoIngestJobsPanel getPendingJobsPanel() {
return pendingJobsPanel;
}
/**
* Update status of the services on the dashboard
*/
private void displayServicesStatus() {
tbServicesStatusMessage.setText(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.tbServicesStatusMessage.Message",
statusByService.get(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString()),
statusByService.get(ServicesMonitor.Service.REMOTE_KEYWORD_SEARCH.toString()),
statusByService.get(ServicesMonitor.Service.REMOTE_KEYWORD_SEARCH.toString()),
tbServicesStatusMessage.setText(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.tbServicesStatusMessage.Message",
statusByService.get(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString()),
statusByService.get(ServicesMonitor.Service.REMOTE_KEYWORD_SEARCH.toString()),
statusByService.get(ServicesMonitor.Service.REMOTE_KEYWORD_SEARCH.toString()),
statusByService.get(ServicesMonitor.Service.MESSAGING.toString())));
String upStatus = NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.tbServicesStatusMessage.Message.Up");
if (statusByService.get(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString()).compareTo(upStatus) != 0
@ -162,7 +142,7 @@ final class AutoIngestDashboard extends JPanel implements Observer {
*/
private void setServicesStatusMessage() {
new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
statusByService.put(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString(), getServiceStatus(ServicesMonitor.Service.REMOTE_CASE_DATABASE));
@ -202,233 +182,6 @@ final class AutoIngestDashboard extends JPanel implements Observer {
}.execute();
}
/**
* Sets up the JTable that presents a view of the pending jobs queue for an
* auto ingest cluster.
*/
private void initPendingJobsTable() {
/*
* Remove some of the jobs table model columns from the JTable. This
* does not remove the columns from the model, just from this table.
*/
pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.HOST_NAME.getColumnHeader()));
pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.STARTED_TIME.getColumnHeader()));
pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.COMPLETED_TIME.getColumnHeader()));
pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.STAGE.getColumnHeader()));
pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.STAGE_TIME.getColumnHeader()));
pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader()));
pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.STATUS.getColumnHeader()));
pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader()));
pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.JOB.getColumnHeader()));
/*
* Set up a column to display the cases associated with the jobs.
*/
TableColumn column;
column = pendingTable.getColumn(JobsTableModelColumns.CASE.getColumnHeader());
column.setMinWidth(GENERIC_COL_MIN_WIDTH);
column.setMaxWidth(GENERIC_COL_MAX_WIDTH);
column.setPreferredWidth(PENDING_TABLE_COL_PREFERRED_WIDTH);
column.setWidth(PENDING_TABLE_COL_PREFERRED_WIDTH);
/*
* Set up a column to display the data sources associated with the jobs.
*/
column = pendingTable.getColumn(JobsTableModelColumns.DATA_SOURCE.getColumnHeader());
column.setMaxWidth(GENERIC_COL_MAX_WIDTH);
column.setPreferredWidth(PENDING_TABLE_COL_PREFERRED_WIDTH);
column.setWidth(PENDING_TABLE_COL_PREFERRED_WIDTH);
/*
* Set up a column to display the create times of the jobs.
*/
column = pendingTable.getColumn(JobsTableModelColumns.CREATED_TIME.getColumnHeader());
column.setCellRenderer(new LongDateCellRenderer());
column.setMinWidth(TIME_COL_MIN_WIDTH);
column.setMaxWidth(TIME_COL_MAX_WIDTH);
column.setPreferredWidth(TIME_COL_PREFERRED_WIDTH);
column.setWidth(TIME_COL_PREFERRED_WIDTH);
column = pendingTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader());
column.setCellRenderer(new PrioritizedIconCellRenderer());
column.setMaxWidth(PRIORITY_COLUMN_MAX_WIDTH);
column.setPreferredWidth(PRIORITY_COLUMN_PREFERRED_WIDTH);
column.setWidth(PRIORITY_COLUMN_PREFERRED_WIDTH);
/*
* Allow sorting when a column header is clicked.
*/
pendingTable.setRowSorter(new AutoIngestRowSorter<>(pendingTableModel));
/*
* Create a row selection listener to enable/disable the Prioritize
* button.
*/
pendingTable.getSelectionModel().addListSelectionListener((ListSelectionEvent e) -> {
if (e.getValueIsAdjusting()) {
return;
}
int row = pendingTable.getSelectedRow();
boolean enablePrioritizeButtons = false;
boolean enableDeprioritizeButtons = false;
if (row >= 0 && row < pendingTable.getRowCount()) {
enablePrioritizeButtons = true;
enableDeprioritizeButtons = (Integer) pendingTableModel.getValueAt(row, JobsTableModelColumns.PRIORITY.ordinal()) > 0;
}
this.prioritizeJobButton.setEnabled(enablePrioritizeButtons);
this.prioritizeCaseButton.setEnabled(enablePrioritizeButtons);
this.deprioritizeJobButton.setEnabled(enableDeprioritizeButtons);
this.deprioritizeCaseButton.setEnabled(enableDeprioritizeButtons);
});
}
/**
* Sets up the JTable that presents a view of the running jobs list for an
* auto ingest cluster.
*/
private void initRunningJobsTable() {
/*
* Remove some of the jobs table model columns from the JTable. This
* does not remove the columns from the model, just from this table.
*/
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.CREATED_TIME.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.STARTED_TIME.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.COMPLETED_TIME.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.STATUS.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.JOB.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader()));
/*
* Set up a column to display the cases associated with the jobs.
*/
TableColumn column;
column = runningTable.getColumn(JobsTableModelColumns.CASE.getColumnHeader());
column.setMinWidth(GENERIC_COL_MIN_WIDTH);
column.setMaxWidth(GENERIC_COL_MAX_WIDTH);
column.setPreferredWidth(RUNNING_TABLE_COL_PREFERRED_WIDTH);
column.setWidth(RUNNING_TABLE_COL_PREFERRED_WIDTH);
/*
* Set up a column to display the image folders associated with the
* jobs.
*/
column = runningTable.getColumn(JobsTableModelColumns.DATA_SOURCE.getColumnHeader());
column.setMinWidth(GENERIC_COL_MIN_WIDTH);
column.setMaxWidth(GENERIC_COL_MAX_WIDTH);
column.setPreferredWidth(RUNNING_TABLE_COL_PREFERRED_WIDTH);
column.setWidth(RUNNING_TABLE_COL_PREFERRED_WIDTH);
/*
* Set up a column to display the host names of the cluster nodes
* processing the jobs.
*/
column = runningTable.getColumn(JobsTableModelColumns.HOST_NAME.getColumnHeader());
column.setMinWidth(NAME_COL_MIN_WIDTH);
column.setMaxWidth(NAME_COL_MAX_WIDTH);
column.setPreferredWidth(NAME_COL_PREFERRED_WIDTH);
column.setWidth(NAME_COL_PREFERRED_WIDTH);
/*
* Set up a column to display the ingest activities associated with the
* jobs.
*/
column = runningTable.getColumn(JobsTableModelColumns.STAGE.getColumnHeader());
column.setMinWidth(STAGE_COL_MIN_WIDTH);
column.setMaxWidth(STAGE_COL_MAX_WIDTH);
column.setPreferredWidth(STAGE_COL_PREFERRED_WIDTH);
column.setWidth(STAGE_COL_PREFERRED_WIDTH);
/*
* Set up a column to display the ingest activity times associated with
* the jobs.
*/
column = runningTable.getColumn(JobsTableModelColumns.STAGE_TIME.getColumnHeader());
column.setCellRenderer(new DurationCellRenderer());
column.setMinWidth(GENERIC_COL_MIN_WIDTH);
column.setMaxWidth(STAGE_TIME_COL_MAX_WIDTH);
column.setPreferredWidth(STAGE_TIME_COL_MIN_WIDTH);
column.setWidth(STAGE_TIME_COL_MIN_WIDTH);
/*
* Prevent sorting when a column header is clicked.
*/
runningTable.setAutoCreateRowSorter(false);
}
/**
* Sets up the JTable that presents a view of the completed jobs list for an
* auto ingest cluster.
*/
private void initCompletedJobsTable() {
/*
* Remove some of the jobs table model columns from the JTable. This
* does not remove the columns from the model, just from this table.
*/
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.STARTED_TIME.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.STAGE.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.STAGE_TIME.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.HOST_NAME.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.JOB.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader()));
/*
* Set up a column to display the cases associated with the jobs.
*/
TableColumn column;
column = completedTable.getColumn(JobsTableModelColumns.CASE.getColumnHeader());
column.setMinWidth(COMPLETED_TIME_COL_MIN_WIDTH);
column.setMaxWidth(COMPLETED_TIME_COL_MAX_WIDTH);
column.setPreferredWidth(COMPLETED_TIME_COL_PREFERRED_WIDTH);
column.setWidth(COMPLETED_TIME_COL_PREFERRED_WIDTH);
/*
* Set up a column to display the image folders associated with the
* jobs.
*/
column = completedTable.getColumn(JobsTableModelColumns.DATA_SOURCE.getColumnHeader());
column.setMinWidth(COMPLETED_TIME_COL_MIN_WIDTH);
column.setMaxWidth(COMPLETED_TIME_COL_MAX_WIDTH);
column.setPreferredWidth(COMPLETED_TIME_COL_PREFERRED_WIDTH);
column.setWidth(COMPLETED_TIME_COL_PREFERRED_WIDTH);
/*
* Set up a column to display the create times of the jobs.
*/
column = completedTable.getColumn(JobsTableModelColumns.CREATED_TIME.getColumnHeader());
column.setCellRenderer(new LongDateCellRenderer());
column.setMinWidth(TIME_COL_MIN_WIDTH);
column.setMaxWidth(TIME_COL_MAX_WIDTH);
column.setPreferredWidth(TIME_COL_PREFERRED_WIDTH);
column.setWidth(TIME_COL_PREFERRED_WIDTH);
/*
* Set up a column to display the completed times of the jobs.
*/
column = completedTable.getColumn(JobsTableModelColumns.COMPLETED_TIME.getColumnHeader());
column.setCellRenderer(new LongDateCellRenderer());
column.setMinWidth(TIME_COL_MIN_WIDTH);
column.setMaxWidth(TIME_COL_MAX_WIDTH);
column.setPreferredWidth(TIME_COL_PREFERRED_WIDTH);
column.setWidth(TIME_COL_PREFERRED_WIDTH);
/*
* Set up a column to display the statuses of the jobs, with a cell
* renderer that will choose an icon to represent the job status.
*/
column = completedTable.getColumn(JobsTableModelColumns.STATUS.getColumnHeader());
column.setCellRenderer(new StatusIconCellRenderer());
column.setMinWidth(STATUS_COL_MIN_WIDTH);
column.setMaxWidth(STATUS_COL_MAX_WIDTH);
column.setPreferredWidth(STATUS_COL_PREFERRED_WIDTH);
column.setWidth(STATUS_COL_PREFERRED_WIDTH);
/*
* Allow sorting when a column header is clicked.
*/
completedTable.setRowSorter(new AutoIngestRowSorter<>(completedTableModel));
}
/**
* Starts up the auto ingest monitor and adds this panel as an observer,
* subscribes to services monitor events and starts a task to populate the
@ -437,10 +190,10 @@ final class AutoIngestDashboard extends JPanel implements Observer {
private void startUp() throws AutoIngestMonitor.AutoIngestMonitorException {
PropertyChangeListener propChangeListener = (PropertyChangeEvent evt) -> {
String serviceDisplayName = ServicesMonitor.Service.valueOf(evt.getPropertyName()).toString();
String status = evt.getNewValue().toString();
if (status.equals(ServicesMonitor.ServiceStatus.UP.toString())) {
status = NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.tbServicesStatusMessage.Message.Up");
LOGGER.log(Level.INFO, "Connection to {0} is up", serviceDisplayName); //NON-NLS
@ -450,31 +203,40 @@ final class AutoIngestDashboard extends JPanel implements Observer {
} else {
LOGGER.log(Level.INFO, "Status for {0} is {1}", new Object[]{serviceDisplayName, status}); //NON-NLS
}
// if the status update is for an existing service who's status hasn't changed - do nothing.
if (statusByService.containsKey(serviceDisplayName) && status.equals(statusByService.get(serviceDisplayName))) {
return;
}
statusByService.put(serviceDisplayName, status);
displayServicesStatus();
};
// Subscribe to all multi-user services in order to display their status
Set<String> servicesList = new HashSet<>();
servicesList.add(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString());
servicesList.add(ServicesMonitor.Service.REMOTE_KEYWORD_SEARCH.toString());
servicesList.add(ServicesMonitor.Service.REMOTE_KEYWORD_SEARCH.toString());
servicesList.add(ServicesMonitor.Service.MESSAGING.toString());
ServicesMonitor.getInstance().addSubscriber(servicesList, propChangeListener);
autoIngestMonitor = new AutoIngestMonitor();
autoIngestMonitor.addObserver(this);
autoIngestMonitor.startUp();
new Thread(() -> {
try {
autoIngestMonitor.startUp();
}
catch (AutoIngestMonitor.AutoIngestMonitorException ex) {
LOGGER.log(Level.SEVERE, "Unable to start up Auto Ingest Monitor", ex);
}
}).start();
}
@Override
public void update(Observable observable, Object arg) {
EventQueue.invokeLater(new RefreshComponentsTask((JobsSnapshot) arg));
EventQueue.invokeLater(() -> {
refreshTables();
});
}
/**
@ -483,177 +245,10 @@ final class AutoIngestDashboard extends JPanel implements Observer {
*
* @param jobsSnapshot The jobs snapshot.
*/
private void refreshTables(JobsSnapshot jobsSnapshot) {
List<AutoIngestJob> pendingJobs = jobsSnapshot.getPendingJobs();
List<AutoIngestJob> runningJobs = jobsSnapshot.getRunningJobs();
List<AutoIngestJob> completedJobs = jobsSnapshot.getCompletedJobs();
pendingJobs.sort(new AutoIngestJob.PriorityComparator());
runningJobs.sort(new AutoIngestJob.DataSourceFileNameComparator());
completedJobs.sort(new AutoIngestJob.CompletedDateDescendingComparator());
refreshTable(pendingJobs, pendingTable, pendingTableModel);
refreshTable(runningJobs, runningTable, runningTableModel);
refreshTable(completedJobs, completedTable, completedTableModel);
}
/**
* Reloads the table model for an auto ingest jobs table and refreshes the
* JTable that uses the model.
*
* @param jobs The list of auto ingest jobs.
* @param tableModel The table model.
* @param comparator An optional comparator (may be null) for sorting the
* table model.
*/
private void refreshTable(List<AutoIngestJob> jobs, JTable table, DefaultTableModel tableModel) {
try {
Path currentRow = getSelectedEntry(table, tableModel);
tableModel.setRowCount(0);
for (AutoIngestJob job : jobs) {
AutoIngestJob.StageDetails status = job.getProcessingStageDetails();
tableModel.addRow(new Object[]{
job.getManifest().getCaseName(), // CASE
job.getManifest().getDataSourcePath().getFileName(), job.getProcessingHostName(), // HOST_NAME
job.getManifest().getDateFileCreated(), // CREATED_TIME
job.getProcessingStageStartDate(), // STARTED_TIME
job.getCompletedDate(), // COMPLETED_TIME
status.getDescription(), // STAGE
job.getErrorsOccurred() ? StatusIconCellRenderer.Status.WARNING : StatusIconCellRenderer.Status.OK, // STATUS
((Date.from(Instant.now()).getTime()) - (status.getStartDate().getTime())), // STAGE_TIME
job.getCaseDirectoryPath(), // CASE_DIRECTORY_PATH
job.getManifest().getFilePath(), // MANIFEST_FILE_PATH
job.getPriority(), // PRIORITY
job
});
}
setSelectedEntry(table, tableModel, currentRow);
} catch (Exception ex) {
LOGGER.log(Level.SEVERE, "Error refreshing table " + table.toString(), ex);
}
}
/**
* Gets a path representing the current selection in a table.
*
* @param table The table.
* @param tableModel The table model of the table.
*
* @return A path representing the current selection, or null if there is no
* selection.
*/
Path getSelectedEntry(JTable table, DefaultTableModel tableModel) {
try {
int currentlySelectedRow = table.getSelectedRow();
if (currentlySelectedRow >= 0 && currentlySelectedRow < table.getRowCount()) {
return Paths.get(tableModel.getValueAt(currentlySelectedRow, JobsTableModelColumns.CASE.ordinal()).toString(),
tableModel.getValueAt(currentlySelectedRow, JobsTableModelColumns.DATA_SOURCE.ordinal()).toString());
}
} catch (Exception ignored) {
return null;
}
return null;
}
/**
* Sets the selection of the table to the passed-in path's item, if that
* item exists in the table. If it does not, clears the table selection.
*
* @param table The table.
* @param tableModel The table model of the table.
* @param path The path of the item to set
*/
void setSelectedEntry(JTable table, DefaultTableModel tableModel, Path path) {
if (path != null) {
try {
for (int row = 0; row < table.getRowCount(); ++row) {
Path temp = Paths.get(tableModel.getValueAt(row, JobsTableModelColumns.CASE.ordinal()).toString(),
tableModel.getValueAt(row, JobsTableModelColumns.DATA_SOURCE.ordinal()).toString());
if (temp.compareTo(path) == 0) { // found it
table.setRowSelectionInterval(row, row);
return;
}
}
} catch (Exception ignored) {
table.clearSelection();
}
}
table.clearSelection();
}
/*
* This enum is used in conjunction with the DefaultTableModel class to
* provide table models for the JTables used to display a view of the
* pending jobs queue, running jobs list, and completed jobs list for an
* auto ingest cluster. The enum allows the columns of the table model to be
* described by either an enum ordinal or a column header string.
*/
private enum JobsTableModelColumns {
@Messages({"AutoIngestDashboard.JobsTableModel.ColumnHeader.Priority=Prioritized"})
CASE(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Case")),
DATA_SOURCE(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.ImageFolder")),
HOST_NAME(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.HostName")),
CREATED_TIME(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.CreatedTime")),
STARTED_TIME(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.StartedTime")),
COMPLETED_TIME(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.CompletedTime")),
STAGE(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Stage")),
STAGE_TIME(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.StageTime")),
STATUS(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Status")),
CASE_DIRECTORY_PATH(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.CaseFolder")),
MANIFEST_FILE_PATH(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.ManifestFilePath")),
PRIORITY(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Priority")),
JOB(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Job"));
private final String header;
private JobsTableModelColumns(String header) {
this.header = header;
}
private String getColumnHeader() {
return header;
}
private static final String[] headers = {
CASE.getColumnHeader(),
DATA_SOURCE.getColumnHeader(),
HOST_NAME.getColumnHeader(),
CREATED_TIME.getColumnHeader(),
STARTED_TIME.getColumnHeader(),
COMPLETED_TIME.getColumnHeader(),
STAGE.getColumnHeader(),
STATUS.getColumnHeader(),
STAGE_TIME.getColumnHeader(),
CASE_DIRECTORY_PATH.getColumnHeader(),
MANIFEST_FILE_PATH.getColumnHeader(),
PRIORITY.getColumnHeader(),
JOB.getColumnHeader()
};
};
/**
* A task that refreshes the UI components on this panel to reflect a
* snapshot of the pending, running and completed auto ingest jobs lists of
* an auto ingest cluster.
*/
private class RefreshComponentsTask implements Runnable {
private final JobsSnapshot jobsSnapshot;
/**
* Constructs a task that refreshes the UI components on this panel to
* reflect a snapshot of the pending, running and completed auto ingest
* jobs lists of an auto ingest cluster.
*
* @param jobsSnapshot The jobs snapshot.
*/
RefreshComponentsTask(JobsSnapshot jobsSnapshot) {
this.jobsSnapshot = jobsSnapshot;
}
@Override
public void run() {
refreshTables(jobsSnapshot);
}
void refreshTables() {
pendingJobsPanel.refresh(autoIngestMonitor.getJobsSnapshot());
runningJobsPanel.refresh(autoIngestMonitor.getJobsSnapshot());
completedJobsPanel.refresh(autoIngestMonitor.getJobsSnapshot());
}
/**
@ -698,75 +293,22 @@ final class AutoIngestDashboard extends JPanel implements Observer {
jButton1 = new javax.swing.JButton();
pendingScrollPane = new javax.swing.JScrollPane();
pendingTable = new javax.swing.JTable();
runningScrollPane = new javax.swing.JScrollPane();
runningTable = new javax.swing.JTable();
completedScrollPane = new javax.swing.JScrollPane();
completedTable = new javax.swing.JTable();
lbPending = new javax.swing.JLabel();
lbRunning = new javax.swing.JLabel();
lbCompleted = new javax.swing.JLabel();
refreshButton = new javax.swing.JButton();
lbServicesStatus = new javax.swing.JLabel();
tbServicesStatusMessage = new javax.swing.JTextField();
prioritizeJobButton = new javax.swing.JButton();
prioritizeCaseButton = new javax.swing.JButton();
clusterMetricsButton = new javax.swing.JButton();
deprioritizeJobButton = new javax.swing.JButton();
deprioritizeCaseButton = new javax.swing.JButton();
org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.jButton1.text")); // NOI18N
pendingTable.setModel(pendingTableModel);
pendingTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.pendingTable.toolTipText")); // NOI18N
pendingTable.setRowHeight(20);
pendingTable.setSelectionModel(new DefaultListSelectionModel() {
private static final long serialVersionUID = 1L;
@Override
public void setSelectionInterval(int index0, int index1) {
if (index0 == pendingTable.getSelectedRow()) {
pendingTable.clearSelection();
} else {
super.setSelectionInterval(index0, index1);
}
}
});
pendingTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
pendingScrollPane.setViewportView(pendingTable);
runningTable.setModel(runningTableModel);
runningTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.runningTable.toolTipText")); // NOI18N
runningTable.setRowHeight(20);
runningTable.setSelectionModel(new DefaultListSelectionModel() {
private static final long serialVersionUID = 1L;
@Override
public void setSelectionInterval(int index0, int index1) {
if (index0 == runningTable.getSelectedRow()) {
runningTable.clearSelection();
} else {
super.setSelectionInterval(index0, index1);
}
}
});
runningTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
runningScrollPane.setViewportView(runningTable);
completedTable.setModel(completedTableModel);
completedTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.completedTable.toolTipText")); // NOI18N
completedTable.setRowHeight(20);
completedTable.setSelectionModel(new DefaultListSelectionModel() {
private static final long serialVersionUID = 1L;
@Override
public void setSelectionInterval(int index0, int index1) {
if (index0 == completedTable.getSelectedRow()) {
completedTable.clearSelection();
} else {
super.setSelectionInterval(index0, index1);
}
}
});
completedTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
completedScrollPane.setViewportView(completedTable);
pendingScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
pendingScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
pendingScrollPane.setOpaque(false);
pendingScrollPane.setPreferredSize(new java.awt.Dimension(2, 215));
lbPending.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(lbPending, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.lbPending.text")); // NOI18N
@ -793,24 +335,6 @@ final class AutoIngestDashboard extends JPanel implements Observer {
tbServicesStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.tbServicesStatusMessage.text")); // NOI18N
tbServicesStatusMessage.setBorder(null);
org.openide.awt.Mnemonics.setLocalizedText(prioritizeJobButton, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.prioritizeJobButton.text")); // NOI18N
prioritizeJobButton.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.prioritizeJobButton.toolTipText")); // NOI18N
prioritizeJobButton.setEnabled(false);
prioritizeJobButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
prioritizeJobButtonActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(prioritizeCaseButton, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.prioritizeCaseButton.text")); // NOI18N
prioritizeCaseButton.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.prioritizeCaseButton.toolTipText")); // NOI18N
prioritizeCaseButton.setEnabled(false);
prioritizeCaseButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
prioritizeCaseButtonActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(clusterMetricsButton, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.clusterMetricsButton.text")); // NOI18N
clusterMetricsButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
@ -818,24 +342,6 @@ final class AutoIngestDashboard extends JPanel implements Observer {
}
});
org.openide.awt.Mnemonics.setLocalizedText(deprioritizeJobButton, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.deprioritizeJobButton.text")); // NOI18N
deprioritizeJobButton.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.deprioritizeJobButton.toolTipText")); // NOI18N
deprioritizeJobButton.setEnabled(false);
deprioritizeJobButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
deprioritizeJobButtonActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(deprioritizeCaseButton, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.deprioritizeCaseButton.text")); // NOI18N
deprioritizeCaseButton.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.deprioritizeCaseButton.toolTipText")); // NOI18N
deprioritizeCaseButton.setEnabled(false);
deprioritizeCaseButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
deprioritizeCaseButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
@ -843,35 +349,27 @@ final class AutoIngestDashboard extends JPanel implements Observer {
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(pendingScrollPane)
.addComponent(pendingScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(runningScrollPane, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(completedScrollPane, javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(lbServicesStatus)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(tbServicesStatusMessage, javax.swing.GroupLayout.DEFAULT_SIZE, 861, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(refreshButton, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(prioritizeJobButton, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(deprioritizeJobButton, javax.swing.GroupLayout.PREFERRED_SIZE, 127, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(prioritizeCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(deprioritizeCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 127, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(clusterMetricsButton))
.addComponent(lbPending, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lbCompleted, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lbRunning, javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(lbServicesStatus)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(tbServicesStatusMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 861, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(0, 0, Short.MAX_VALUE)))
.addComponent(lbRunning, javax.swing.GroupLayout.Alignment.LEADING))
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(refreshButton, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(clusterMetricsButton)))
.addContainerGap())
);
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {clusterMetricsButton, prioritizeCaseButton, prioritizeJobButton, refreshButton});
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {clusterMetricsButton, refreshButton});
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -883,23 +381,19 @@ final class AutoIngestDashboard extends JPanel implements Observer {
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lbPending, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(1, 1, 1)
.addComponent(pendingScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(pendingScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(lbRunning)
.addGap(1, 1, 1)
.addComponent(runningScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 133, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(runningScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 133, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(lbCompleted)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(completedScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 179, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(completedScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 179, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(refreshButton)
.addComponent(prioritizeJobButton)
.addComponent(prioritizeCaseButton)
.addComponent(clusterMetricsButton)
.addComponent(deprioritizeJobButton)
.addComponent(deprioritizeCaseButton))
.addComponent(clusterMetricsButton))
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
@ -913,135 +407,25 @@ final class AutoIngestDashboard extends JPanel implements Observer {
*/
private void refreshButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshButtonActionPerformed
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
JobsSnapshot jobsSnapshot = autoIngestMonitor.refreshJobsSnapshot();
refreshTables(jobsSnapshot);
refreshTables();
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}//GEN-LAST:event_refreshButtonActionPerformed
@Messages({"AutoIngestDashboard.errorMessage.jobPrioritization=Failed to prioritize job \"%s\"."})
private void prioritizeJobButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_prioritizeJobButtonActionPerformed
if (pendingTableModel.getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
AutoIngestJob job = (AutoIngestJob) (pendingTableModel.getValueAt(pendingTable.getSelectedRow(), JobsTableModelColumns.JOB.ordinal()));
JobsSnapshot jobsSnapshot;
try {
jobsSnapshot = autoIngestMonitor.prioritizeJob(job);
refreshTables(jobsSnapshot);
} catch (AutoIngestMonitor.AutoIngestMonitorException ex) {
String errorMessage = String.format(Bundle.AutoIngestDashboard_errorMessage_jobPrioritization(), job.getManifest().getFilePath());
LOGGER.log(Level.SEVERE, errorMessage, ex);
MessageNotifyUtil.Message.error(errorMessage);
}
setCursor(Cursor.getDefaultCursor());
}
}//GEN-LAST:event_prioritizeJobButtonActionPerformed
@Messages({"AutoIngestDashboard.errorMessage.casePrioritization=Failed to prioritize case \"%s\"."})
private void prioritizeCaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_prioritizeCaseButtonActionPerformed
if (pendingTableModel.getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
String caseName = (pendingTableModel.getValueAt(pendingTable.getSelectedRow(), JobsTableModelColumns.CASE.ordinal())).toString();
JobsSnapshot jobsSnapshot;
try {
jobsSnapshot = autoIngestMonitor.prioritizeCase(caseName);
refreshTables(jobsSnapshot);
} catch (AutoIngestMonitor.AutoIngestMonitorException ex) {
String errorMessage = String.format(Bundle.AutoIngestDashboard_errorMessage_casePrioritization(), caseName);
LOGGER.log(Level.SEVERE, errorMessage, ex);
MessageNotifyUtil.Message.error(errorMessage);
}
setCursor(Cursor.getDefaultCursor());
}
}//GEN-LAST:event_prioritizeCaseButtonActionPerformed
private void clusterMetricsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_clusterMetricsButtonActionPerformed
new AutoIngestMetricsDialog(this.getTopLevelAncestor());
}//GEN-LAST:event_clusterMetricsButtonActionPerformed
@Messages({"AutoIngestDashboard.errorMessage.jobDeprioritization=Failed to deprioritize job \"%s\"."})
private void deprioritizeJobButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deprioritizeJobButtonActionPerformed
if (pendingTableModel.getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
AutoIngestJob job = (AutoIngestJob) (pendingTableModel.getValueAt(pendingTable.getSelectedRow(), JobsTableModelColumns.JOB.ordinal()));
JobsSnapshot jobsSnapshot;
try {
jobsSnapshot = autoIngestMonitor.deprioritizeJob(job);
refreshTables(jobsSnapshot);
} catch (AutoIngestMonitor.AutoIngestMonitorException ex) {
String errorMessage = String.format(Bundle.AutoIngestDashboard_errorMessage_jobDeprioritization(), job.getManifest().getFilePath());
LOGGER.log(Level.SEVERE, errorMessage, ex);
MessageNotifyUtil.Message.error(errorMessage);
}
setCursor(Cursor.getDefaultCursor());
}
}//GEN-LAST:event_deprioritizeJobButtonActionPerformed
@Messages({"AutoIngestDashboard.errorMessage.caseDeprioritization=Failed to deprioritize case \"%s\"."})
private void deprioritizeCaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deprioritizeCaseButtonActionPerformed
if (pendingTableModel.getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
String caseName = (pendingTableModel.getValueAt(pendingTable.getSelectedRow(), JobsTableModelColumns.CASE.ordinal())).toString();
JobsSnapshot jobsSnapshot;
try {
jobsSnapshot = autoIngestMonitor.deprioritizeCase(caseName);
refreshTables(jobsSnapshot);
} catch (AutoIngestMonitor.AutoIngestMonitorException ex) {
String errorMessage = String.format(Bundle.AutoIngestDashboard_errorMessage_caseDeprioritization(), caseName);
LOGGER.log(Level.SEVERE, errorMessage, ex);
MessageNotifyUtil.Message.error(errorMessage);
}
setCursor(Cursor.getDefaultCursor());
}
}//GEN-LAST:event_deprioritizeCaseButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton clusterMetricsButton;
private javax.swing.JScrollPane completedScrollPane;
private javax.swing.JTable completedTable;
private javax.swing.JButton deprioritizeCaseButton;
private javax.swing.JButton deprioritizeJobButton;
private javax.swing.JButton jButton1;
private javax.swing.JLabel lbCompleted;
private javax.swing.JLabel lbPending;
private javax.swing.JLabel lbRunning;
private javax.swing.JLabel lbServicesStatus;
private javax.swing.JScrollPane pendingScrollPane;
private javax.swing.JTable pendingTable;
private javax.swing.JButton prioritizeCaseButton;
private javax.swing.JButton prioritizeJobButton;
private javax.swing.JButton refreshButton;
private javax.swing.JScrollPane runningScrollPane;
private javax.swing.JTable runningTable;
private javax.swing.JTextField tbServicesStatusMessage;
// End of variables declaration//GEN-END:variables
private class AutoIngestTableModel extends DefaultTableModel {
private static final long serialVersionUID = 1L;
private AutoIngestTableModel(String[] headers, int i) {
super(headers, i);
}
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == JobsTableModelColumns.PRIORITY.ordinal()) {
return Integer.class;
} else if (columnIndex == JobsTableModelColumns.CREATED_TIME.ordinal()
|| columnIndex == JobsTableModelColumns.COMPLETED_TIME.ordinal()
|| columnIndex == JobsTableModelColumns.STARTED_TIME.ordinal()
|| columnIndex == JobsTableModelColumns.STAGE_TIME.ordinal()) {
return Date.class;
} else if (columnIndex == JobsTableModelColumns.STATUS.ordinal()) {
return Boolean.class;
} else {
return super.getColumnClass(columnIndex);
}
}
}
}

View File

@ -25,4 +25,4 @@
</Group>
</DimensionLayout>
</Layout>
</Form>
</Form>

View File

@ -18,6 +18,7 @@
*/
package org.sleuthkit.autopsy.experimental.autoingest;
import java.awt.Component;
import java.util.List;
import java.util.logging.Level;
import java.util.stream.Collectors;
@ -74,7 +75,7 @@ public final class AutoIngestDashboardTopComponent extends TopComponent {
AutoIngestDashboard dashboard = AutoIngestDashboard.createDashboard();
tc.add(dashboard);
dashboard.setSize(dashboard.getPreferredSize());
tc.open();
}
tc.toFront();
@ -104,6 +105,20 @@ public final class AutoIngestDashboardTopComponent extends TopComponent {
setName(Bundle.CTL_AutoIngestDashboardTopComponent());
}
/**
* Get the current AutoIngestDashboard if there is one.
*
* @return the current AutoIngestDashboard or null if there is not one
*/
AutoIngestDashboard getAutoIngestDashboard() {
for (Component comp : getComponents()) {
if (comp instanceof AutoIngestDashboard) {
return (AutoIngestDashboard) comp;
}
}
return null;
}
@Override
public List<Mode> availableModes(List<Mode> modes) {
/*

View File

@ -0,0 +1,235 @@
/*
* 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.experimental.autoingest;
import java.io.File;
import javax.swing.Action;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.openide.modules.Places;
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.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.datamodel.NodeProperty;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestMonitor.JobsSnapshot;
import org.sleuthkit.autopsy.guiutils.DurationCellRenderer;
import org.sleuthkit.autopsy.guiutils.StatusIconCellRenderer;
/**
* A node which represents all AutoIngestJobs of a given AutoIngestJobStatus.
* Each job with the specified status will have a child node representing it.
*/
final class AutoIngestJobsNode extends AbstractNode {
private final static String ADMIN_ACCESS_FILE_NAME = "adminAccess";
private final static String ADMIN_ACCESS_FILE_PATH = Places.getUserDirectory().getAbsolutePath() + File.separator + ADMIN_ACCESS_FILE_NAME;
@Messages({
"AutoIngestJobsNode.caseName.text=Case Name",
"AutoIngestJobsNode.dataSource.text=Data Source",
"AutoIngestJobsNode.hostName.text=Host Name",
"AutoIngestJobsNode.stage.text=Stage",
"AutoIngestJobsNode.stageTime.text=Time in Stage",
"AutoIngestJobsNode.jobCreated.text=Job Created",
"AutoIngestJobsNode.jobCompleted.text=Job Completed",
"AutoIngestJobsNode.priority.text=Prioritized",
"AutoIngestJobsNode.status.text=Status"
})
/**
* Construct a new AutoIngestJobsNode.
*/
AutoIngestJobsNode(JobsSnapshot jobsSnapshot, AutoIngestJobStatus status) {
super(Children.create(new AutoIngestNodeChildren(jobsSnapshot, status), false));
}
/**
* A ChildFactory for generating JobNodes.
*/
static class AutoIngestNodeChildren extends ChildFactory<AutoIngestJob> {
private final AutoIngestJobStatus autoIngestJobStatus;
private final JobsSnapshot jobsSnapshot;
/**
* Create children nodes for the AutoIngestJobsNode which will each
* represent a single AutoIngestJob
*
* @param snapshot the snapshot which contains the AutoIngestJobs
* @param status the status of the jobs being displayed
*/
AutoIngestNodeChildren(JobsSnapshot snapshot, AutoIngestJobStatus status) {
jobsSnapshot = snapshot;
autoIngestJobStatus = status;
}
@Override
protected boolean createKeys(List<AutoIngestJob> list) {
List<AutoIngestJob> jobs;
switch (autoIngestJobStatus) {
case PENDING_JOB:
jobs = jobsSnapshot.getPendingJobs();
jobs.sort(new AutoIngestJob.PriorityComparator());
break;
case RUNNING_JOB:
jobs = jobsSnapshot.getRunningJobs();
break;
case COMPLETED_JOB:
jobs = jobsSnapshot.getCompletedJobs();
break;
default:
jobs = new ArrayList<>();
}
if (jobs != null && jobs.size() > 0) {
list.addAll(jobs);
}
return true;
}
@Override
protected Node createNodeForKey(AutoIngestJob key) {
return new JobNode(key, autoIngestJobStatus);
}
}
/**
* A node which represents a single auto ingest job.
*/
static final class JobNode extends AbstractNode {
private final AutoIngestJob autoIngestJob;
private final AutoIngestJobStatus jobStatus;
/**
* Construct a new JobNode to represent an AutoIngestJob and its status.
*
* @param job - the AutoIngestJob being represented by this node
* @param status - the current status of the AutoIngestJob being
* represented
*/
JobNode(AutoIngestJob job, AutoIngestJobStatus status) {
super(Children.LEAF);
jobStatus = status;
autoIngestJob = job;
super.setName(autoIngestJob.getManifest().getCaseName());
setName(autoIngestJob.getManifest().getCaseName());
setDisplayName(autoIngestJob.getManifest().getCaseName());
}
/**
* Get the AutoIngestJob which this node represents.
*
* @return autoIngestJob
*/
AutoIngestJob getAutoIngestJob() {
return autoIngestJob;
}
@Override
@Messages({"AutoIngestJobsNode.prioritized.true=Yes",
"AutoIngestJobsNode.prioritized.false=No"
})
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
}
ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_caseName_text(), Bundle.AutoIngestJobsNode_caseName_text(), Bundle.AutoIngestJobsNode_caseName_text(),
autoIngestJob.getManifest().getCaseName()));
ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_dataSource_text(), Bundle.AutoIngestJobsNode_dataSource_text(), Bundle.AutoIngestJobsNode_dataSource_text(),
autoIngestJob.getManifest().getDataSourcePath().getFileName().toString()));
switch (jobStatus) {
case PENDING_JOB:
ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_jobCreated_text(), Bundle.AutoIngestJobsNode_jobCreated_text(), Bundle.AutoIngestJobsNode_jobCreated_text(),
autoIngestJob.getManifest().getDateFileCreated()));
ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_priority_text(), Bundle.AutoIngestJobsNode_priority_text(), Bundle.AutoIngestJobsNode_priority_text(),
autoIngestJob.getPriority() > 0 ? Bundle.AutoIngestJobsNode_prioritized_true() : Bundle.AutoIngestJobsNode_prioritized_false()));
break;
case RUNNING_JOB:
AutoIngestJob.StageDetails status = autoIngestJob.getProcessingStageDetails();
ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_hostName_text(), Bundle.AutoIngestJobsNode_hostName_text(), Bundle.AutoIngestJobsNode_hostName_text(),
autoIngestJob.getProcessingHostName()));
ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_stage_text(), Bundle.AutoIngestJobsNode_stage_text(), Bundle.AutoIngestJobsNode_stage_text(),
status.getDescription()));
ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_stageTime_text(), Bundle.AutoIngestJobsNode_stageTime_text(), Bundle.AutoIngestJobsNode_stageTime_text(),
DurationCellRenderer.longToDurationString((Date.from(Instant.now()).getTime()) - (status.getStartDate().getTime()))));
break;
case COMPLETED_JOB:
ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_jobCreated_text(), Bundle.AutoIngestJobsNode_jobCreated_text(), Bundle.AutoIngestJobsNode_jobCreated_text(),
autoIngestJob.getManifest().getDateFileCreated()));
ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_jobCompleted_text(), Bundle.AutoIngestJobsNode_jobCompleted_text(), Bundle.AutoIngestJobsNode_jobCompleted_text(),
autoIngestJob.getCompletedDate()));
ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_status_text(), Bundle.AutoIngestJobsNode_status_text(), Bundle.AutoIngestJobsNode_status_text(),
autoIngestJob.getErrorsOccurred() ? StatusIconCellRenderer.Status.WARNING : StatusIconCellRenderer.Status.OK));
break;
default:
}
return s;
}
@Override
public Action[] getActions(boolean context) {
List<Action> actions = new ArrayList<>();
File f = new File(ADMIN_ACCESS_FILE_PATH);
if (f.exists()) {
switch (jobStatus) {
case PENDING_JOB:
actions.add(new PrioritizationAction.PrioritizeJobAction(autoIngestJob));
actions.add(new PrioritizationAction.PrioritizeCaseAction(autoIngestJob));
PrioritizationAction.DeprioritizeJobAction deprioritizeJobAction = new PrioritizationAction.DeprioritizeJobAction(autoIngestJob);
deprioritizeJobAction.setEnabled(autoIngestJob.getPriority() > 0);
actions.add(deprioritizeJobAction);
PrioritizationAction.DeprioritizeCaseAction deprioritizeCaseAction = new PrioritizationAction.DeprioritizeCaseAction(autoIngestJob);
deprioritizeCaseAction.setEnabled(autoIngestJob.getPriority() > 0);
actions.add(deprioritizeCaseAction);
break;
case RUNNING_JOB:
actions.add(new AutoIngestAdminActions.ProgressDialogAction());
actions.add(new AutoIngestAdminActions.CancelJobAction());
actions.add(new AutoIngestAdminActions.CancelModuleAction());
break;
case COMPLETED_JOB:
actions.add(new AutoIngestAdminActions.ReprocessJobAction());
actions.add(new AutoIngestAdminActions.DeleteCaseAction());
actions.add(new AutoIngestAdminActions.ShowCaseLogAction());
break;
default:
}
}
return actions.toArray(new Action[actions.size()]);
}
}
/**
* An enumeration used to indicate the current status of an auto ingest job
* node.
*/
enum AutoIngestJobStatus {
PENDING_JOB, //NON-NLS
RUNNING_JOB, //NON-NLS
COMPLETED_JOB //NON-NLS
}
}

View File

@ -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,0,7,0,0,0,29"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
</Form>

View File

@ -0,0 +1,211 @@
/*
* 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.experimental.autoingest;
import java.awt.Dimension;
import java.beans.PropertyVetoException;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionListener;
import org.netbeans.swing.outline.DefaultOutlineModel;
import org.netbeans.swing.outline.Outline;
import org.openide.explorer.ExplorerManager;
import org.openide.nodes.Node;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.datamodel.EmptyNode;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobsNode.AutoIngestJobStatus;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobsNode.JobNode;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestMonitor.JobsSnapshot;
/**
* A panel which displays an outline view with all jobs for a specified status.
*/
final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerManager.Provider {
private static final long serialVersionUID = 1L;
private static final int INITIAL_CASENAME_WIDTH = 170;
private static final int INITIAL_DATASOURCE_WIDTH = 270;
private static final int INITIAL_PRIORITIZED_WIDTH = 20;
private static final int INITIAL_STATUS_WIDTH = 20;
private static final int INVALID_INDEX = -1;
private final org.openide.explorer.view.OutlineView outlineView;
private final Outline outline;
private ExplorerManager explorerManager;
private final AutoIngestJobStatus status;
/**
* Creates a new AutoIngestJobsPanel of the specified jobStatus
*
* @param jobStatus the status of the jbos to be displayed on this panel
*/
AutoIngestJobsPanel(AutoIngestJobStatus jobStatus) {
initComponents();
status = jobStatus;
outlineView = new org.openide.explorer.view.OutlineView();
outline = outlineView.getOutline();
customize();
}
/**
* Set up the AutoIngestJobsPanel's so that its outlineView is displaying
* the correct columns for the specified AutoIngestJobStatus
*/
@Messages({"AutoIngestJobsPanel.waitNode.text=Please Wait..."})
void customize() {
((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.AutoIngestJobsNode_caseName_text());
outline.setRowSelectionAllowed(false); //rows will be made selectable after table has been populated
outline.setFocusable(false); //table will be made focusable after table has been populated
if (null == explorerManager) {
explorerManager = new ExplorerManager();
}
explorerManager.setRootContext(new EmptyNode(Bundle.AutoIngestJobsPanel_waitNode_text()));
int indexOfColumn;
switch (status) {
case PENDING_JOB:
outlineView.setPropertyColumns(Bundle.AutoIngestJobsNode_dataSource_text(), Bundle.AutoIngestJobsNode_dataSource_text(),
Bundle.AutoIngestJobsNode_jobCreated_text(), Bundle.AutoIngestJobsNode_jobCreated_text(),
Bundle.AutoIngestJobsNode_priority_text(), Bundle.AutoIngestJobsNode_priority_text());
indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_priority_text());
if (indexOfColumn != INVALID_INDEX) {
outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_PRIORITIZED_WIDTH);
}
break;
case RUNNING_JOB:
outlineView.setPropertyColumns(Bundle.AutoIngestJobsNode_dataSource_text(), Bundle.AutoIngestJobsNode_dataSource_text(),
Bundle.AutoIngestJobsNode_hostName_text(), Bundle.AutoIngestJobsNode_hostName_text(),
Bundle.AutoIngestJobsNode_stage_text(), Bundle.AutoIngestJobsNode_stage_text(),
Bundle.AutoIngestJobsNode_stageTime_text(), Bundle.AutoIngestJobsNode_stageTime_text());
indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_caseName_text());
if (indexOfColumn != INVALID_INDEX) {
outline.setColumnSorted(indexOfColumn, true, 1);
}
break;
case COMPLETED_JOB:
outlineView.setPropertyColumns(Bundle.AutoIngestJobsNode_dataSource_text(), Bundle.AutoIngestJobsNode_dataSource_text(),
Bundle.AutoIngestJobsNode_jobCreated_text(), Bundle.AutoIngestJobsNode_jobCreated_text(),
Bundle.AutoIngestJobsNode_jobCompleted_text(), Bundle.AutoIngestJobsNode_jobCompleted_text(),
Bundle.AutoIngestJobsNode_status_text(), Bundle.AutoIngestJobsNode_status_text());
indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_jobCompleted_text());
if (indexOfColumn != INVALID_INDEX) {
outline.setColumnSorted(indexOfColumn, false, 1);
}
indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_status_text());
if (indexOfColumn != INVALID_INDEX) {
outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_STATUS_WIDTH);
}
break;
default:
}
outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
outline.setRootVisible(false);
indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_caseName_text());
if (indexOfColumn != INVALID_INDEX) {
outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_CASENAME_WIDTH);
}
indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_dataSource_text());
if (indexOfColumn != INVALID_INDEX) {
outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_DATASOURCE_WIDTH);
}
add(outlineView, java.awt.BorderLayout.CENTER);
}
private int getColumnIndexByName(String columnName) {
for (int index = 0; index < outline.getColumnModel().getColumnCount(); index++) {
if (outline.getColumnModel().getColumn(index).getHeaderValue().toString().equals(columnName)) {
return index;
}
}
return INVALID_INDEX;
}
@Override
public void setSize(Dimension d) {
super.setSize(d);
outlineView.setMaximumSize(new Dimension(400, 100));
outline.setPreferredScrollableViewportSize(new Dimension(400, 100));
}
/**
* Add a list selection listener to the selection model of the outline being
* used in this panel.
*
* @param listener the ListSelectionListener to add
*/
void addListSelectionListener(ListSelectionListener listener) {
outline.getSelectionModel().addListSelectionListener(listener);
}
@Override
public ExplorerManager getExplorerManager() {
return explorerManager;
}
/**
* Update the contents of this AutoIngestJobsPanel while retaining currently
* selected node.
*
* @param jobsSnapshot - the JobsSnapshot which will provide the new
* contents
*/
void refresh(JobsSnapshot jobsSnapshot) {
synchronized (this) {
outline.setRowSelectionAllowed(false);
Node[] selectedNodes = explorerManager.getSelectedNodes();
AutoIngestJobsNode autoIngestNode = new AutoIngestJobsNode(jobsSnapshot, status);
explorerManager.setRootContext(autoIngestNode);
outline.setRowSelectionAllowed(true);
if (selectedNodes.length > 0 && outline.isFocusable()) { //don't allow saved selections of empty nodes to be restored
try {
explorerManager.setSelectedNodes(new Node[]{autoIngestNode.getChildren().findChild(selectedNodes[0].getName())});
} catch (PropertyVetoException ignore) {
//Unable to select previously selected node
}
}
outline.setFocusable(true);
}
}
/**
* 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
/**
* Get the AutoIngestJob for the currently selected node of this panel.
*
* @return AutoIngestJob which is currently selected in this panel
*/
AutoIngestJob getSelectedAutoIngestJob() {
Node[] selectedRows = explorerManager.getSelectedNodes();
if (selectedRows.length == 1) {
return ((JobNode) selectedRows[0]).getAutoIngestJob();
}
return null;
}
// Variables declaration - do not modify//GEN-BEGIN:variables
// End of variables declaration//GEN-END:variables
}

View File

@ -10,9 +10,6 @@ AutoIngestDashboard.JobsTableModel.ColumnHeader.CompletedTime=Job Completed
AutoIngestDashboard.JobsTableModel.ColumnHeader.Stage=Stage
AutoIngestDashboard.JobsTableModel.ColumnHeader.Status=Status
AutoIngestDashboard.JobsTableModel.ColumnHeader.ManifestFilePath= Manifest File Path
AutoIngestDashboard.pendingTable.toolTipText=The Pending table displays the order upcoming Jobs will be processed with the top of the list first
AutoIngestDashboard.runningTable.toolTipText=The Running table displays the currently running Job and information about it
AutoIngestDashboard.completedTable.toolTipText=The Completed table shows all Jobs that have been processed already
AutoIngestDashboard.JobsTableModel.ColumnHeader.StageTime=Time in Stage
AutoIngestDashboard.JobsTableModel.ColumnHeader.CaseFolder=Case
AutoIngestDashboard.JobsTableModel.ColumnHeader.Job=Job
@ -222,10 +219,6 @@ FileExporterSettingsPanel.SaveTooltip_1=Save the current rule
AutoIngestDashboard.refreshButton.toolTipText=Refresh displayed tables
AutoIngestDashboard.refreshButton.text=&Refresh
AutoIngestDashboard.jButton1.text=jButton1
AutoIngestDashboard.prioritizeJobButton.toolTipText=Move the selected job to the top of the Pending queue.
AutoIngestDashboard.prioritizeJobButton.text=Prioritize &Job
AutoIngestDashboard.prioritizeCaseButton.toolTipText=Move all images associated with a case to top of Pending queue.
AutoIngestDashboard.prioritizeCaseButton.text=Prioritize &Case
AutoIngestMetricsDialog.reportTextArea.text=
AutoIngestDashboard.clusterMetricsButton.text=Auto Ingest &Metrics
AutoIngestMetricsDialog.metricsButton.text=Generate Metrics Report
@ -236,10 +229,6 @@ ArchiveFilePanel.browseButton.text=Browse
ArchiveFilePanel.pathTextField.text=
ArchiveFilePanel.errorLabel.text=Error Label
AutoIngestMetricsDialog.startingDataLabel.text=Starting Date:
AutoIngestDashboard.deprioritizeJobButton.toolTipText=Move the selected job to the top of the Pending queue.
AutoIngestDashboard.deprioritizeJobButton.text=Deprioritize J&ob
AutoIngestDashboard.deprioritizeCaseButton.text=Deprioritize C&ase
AutoIngestDashboard.deprioritizeCaseButton.toolTipText=Move all images associated with a case to top of Pending queue.
AutoIngestControlPanel.bnDeprioritizeCase.text=Deprioritize Case
AutoIngestControlPanel.bnDeprioritizeJob.text=Deprioritize Job
AutoIngestControlPanel.bnPrioritizeCase.text=Prioritize Case

View File

@ -0,0 +1,249 @@
/*
* 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.experimental.autoingest;
import java.awt.Cursor;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.util.logging.Level;
import javax.swing.AbstractAction;
import org.openide.util.NbBundle.Messages;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
/**
* Abstract actions which are for the modification of AutoIngestJob or Case
* priority.
*/
abstract class PrioritizationAction extends AbstractAction {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(PrioritizationAction.class.getName());
private final AutoIngestJob job;
/**
* Construct a new Prioritization action for the selected job
*
* @param selectedJob The job which will be used to determine what has it's
* priority modified
* @param title - the string to represent the action in menus
*/
PrioritizationAction(AutoIngestJob selectedJob, String title) {
super(title);
job = selectedJob;
}
/**
* The implementation specific method which modifies job or case priority
*
* @param monitor - the AutoIngestMonitor which can be accessed to change
* the job or case priority
*
* @throws
* org.sleuthkit.autopsy.experimental.autoingest.AutoIngestMonitor.AutoIngestMonitorException
*/
protected abstract void modifyPriority(AutoIngestMonitor monitor) throws AutoIngestMonitor.AutoIngestMonitorException;
/**
* Get the implementation specific error message for if modifyPriority fails
*
* @return the error message for the current implementation
*/
protected abstract String getErrorMessage();
/**
* Gets the job this action is constructed for
*
* @return job - the AutoIngestJob
*/
protected AutoIngestJob getJob() {
return job;
}
@Override
public void actionPerformed(ActionEvent e) {
if (job != null) {
final AutoIngestDashboardTopComponent tc = (AutoIngestDashboardTopComponent) WindowManager.getDefault().findTopComponent(AutoIngestDashboardTopComponent.PREFERRED_ID);
if (tc != null) {
AutoIngestDashboard dashboard = tc.getAutoIngestDashboard();
if (dashboard != null) {
dashboard.getPendingJobsPanel().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
EventQueue.invokeLater(() -> {
try {
modifyPriority(dashboard.getMonitor());
dashboard.getPendingJobsPanel().refresh(dashboard.getMonitor().getJobsSnapshot());
} catch (AutoIngestMonitor.AutoIngestMonitorException ex) {
String errorMessage = getErrorMessage();
logger.log(Level.SEVERE, errorMessage, ex);
MessageNotifyUtil.Message.error(errorMessage);
} finally {
dashboard.getPendingJobsPanel().setCursor(Cursor.getDefaultCursor());
}
});
}
}
}
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); //To change body of generated methods, choose Tools | Templates.
}
/**
* Action to prioritize the specified AutoIngestJob
*/
@Messages({"PrioritizationAction.prioritizeJobAction.title=Prioritize Job",
"PrioritizationAction.prioritizeJobAction.error=Failed to prioritize job \"%s\"."})
static final class PrioritizeJobAction extends PrioritizationAction {
private static final long serialVersionUID = 1L;
/**
* Construct a new PrioritizeJobAction
*
* @param selectedJob - the AutoIngestJob to be prioritized
*/
PrioritizeJobAction(AutoIngestJob selectedJob) {
super(selectedJob, Bundle.PrioritizationAction_prioritizeJobAction_title());
}
@Override
protected void modifyPriority(AutoIngestMonitor monitor) throws AutoIngestMonitor.AutoIngestMonitorException {
monitor.prioritizeJob(getJob());
}
@Override
protected String getErrorMessage() {
return String.format(Bundle.PrioritizationAction_prioritizeJobAction_error(), getJob().getManifest().getFilePath());
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); //To change body of generated methods, choose Tools | Templates.
}
}
/**
* Action to deprioritize the specified AutoIngestJob
*/
@Messages({"PrioritizationAction.deprioritizeJobAction.title=Deprioritize Job",
"PrioritizationAction.deprioritizeJobAction.error=Failed to deprioritize job \"%s\"."})
static final class DeprioritizeJobAction extends PrioritizationAction {
private static final long serialVersionUID = 1L;
/**
* Construct a new DeprioritizeJobAction
*
* @param selectedJob - the AutoIngestJob to be deprioritized
*/
DeprioritizeJobAction(AutoIngestJob selectedJob) {
super(selectedJob, Bundle.PrioritizationAction_deprioritizeJobAction_title());
}
@Override
protected void modifyPriority(AutoIngestMonitor monitor) throws AutoIngestMonitor.AutoIngestMonitorException {
monitor.deprioritizeJob(getJob());
}
@Override
protected String getErrorMessage() {
return String.format(Bundle.PrioritizationAction_deprioritizeJobAction_error(), getJob().getManifest().getFilePath());
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); //To change body of generated methods, choose Tools | Templates.
}
}
/**
* Action to prioritize all jobs for the case which the specified
* AutoIngestJob is a part of.
*/
@Messages({"PrioritizationAction.prioritizeCaseAction.title=Prioritize Case",
"PrioritizationAction.prioritizeCaseAction.error==Failed to prioritize case \"%s\"."})
static final class PrioritizeCaseAction extends PrioritizationAction {
private static final long serialVersionUID = 1L;
/**
* Construct a new PrioritizeCaseAction
*
* @param selectedJob - the AutoIngestJob which should have it's case
* prioritized
*/
PrioritizeCaseAction(AutoIngestJob selectedJob) {
super(selectedJob, Bundle.PrioritizationAction_prioritizeCaseAction_title());
}
@Override
protected void modifyPriority(AutoIngestMonitor monitor) throws AutoIngestMonitor.AutoIngestMonitorException {
monitor.prioritizeCase(getJob().getManifest().getCaseName());
}
@Override
protected String getErrorMessage() {
return String.format(Bundle.PrioritizationAction_prioritizeCaseAction_error(), getJob().getManifest().getCaseName());
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); //To change body of generated methods, choose Tools | Templates.
}
}
/**
* Action to deprioritize all jobs for the case which the specified
* AutoIngestJob is a part of.
*/
@Messages({"PrioritizationAction.deprioritizeCaseAction.title=Deprioritize Case",
"PrioritizationAction.deprioritizeCaseAction.error=Failed to deprioritize case \"%s\"."})
static final class DeprioritizeCaseAction extends PrioritizationAction {
private static final long serialVersionUID = 1L;
/**
* Construct a new DeprioritizeCaseAction
*
* @param selectedJob - the AutoIngestJob which should have it's case
* deprioritized
*/
DeprioritizeCaseAction(AutoIngestJob selectedJob) {
super(selectedJob, Bundle.PrioritizationAction_deprioritizeCaseAction_title());
}
@Override
protected void modifyPriority(AutoIngestMonitor monitor) throws AutoIngestMonitor.AutoIngestMonitorException {
monitor.deprioritizeCase(getJob().getManifest().getCaseName());
}
@Override
protected String getErrorMessage() {
return String.format(Bundle.PrioritizationAction_deprioritizeCaseAction_error(), getJob().getManifest().getCaseName());
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); //To change body of generated methods, choose Tools | Templates.
}
}
}

View File

@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import javax.swing.JMenuItem;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
@ -135,8 +136,22 @@ public class DropdownSingleTermSearchPanel extends KeywordSearchPanel {
*
* @return The keyword list.
*/
@NbBundle.Messages({"DropdownSingleTermSearchPanel.warning.title=Warning",
"DropdownSingleTermSearchPanel.warning.text=Boundary characters ^ and $ do not match word boundaries. Consider\nreplacing with an explicit list of boundary characters, such as [ \\.,]"})
@Override
List<KeywordList> getKeywordLists() {
if (regexRadioButton.isSelected()) {
if((keywordTextField.getText() != null) &&
(keywordTextField.getText().startsWith("^") ||
(keywordTextField.getText().endsWith("$") && ! keywordTextField.getText().endsWith("\\$")))) {
KeywordSearchUtil.displayDialog(NbBundle.getMessage(this.getClass(), "DropdownSingleTermSearchPanel.warning.title"),
NbBundle.getMessage(this.getClass(), "DropdownSingleTermSearchPanel.warning.text"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);
}
}
List<Keyword> keywords = new ArrayList<>();
keywords.add(new Keyword(keywordTextField.getText(), !regexRadioButton.isSelected(), exactRadioButton.isSelected()));
List<KeywordList> keywordLists = new ArrayList<>();

View File

@ -27,7 +27,7 @@
</NonVisualComponents>
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[717, 58]"/>
<Dimension value="[100, 58]"/>
</Property>
</Properties>
<AuxValues>
@ -45,74 +45,16 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="hitLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="hitCountLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="hitOfLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="hitTotalLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="hitButtonsLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="hitPreviousButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="hitNextButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="jSeparator2" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="pagesLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="pageCurLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="pageOfLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="pageTotalLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" min="-2" max="-2" attributes="0"/>
<Component id="pageButtonsLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="pagePreviousButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="pageNextButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="jSeparator1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="sourceComboBox" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
<Component id="jScrollPane1" max="32767" attributes="0"/>
<Component id="jScrollPane2" alignment="0" pref="100" max="32767" attributes="0"/>
<Component id="jScrollPane1" alignment="0" pref="100" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jScrollPane2" min="-2" pref="46" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="2" attributes="0">
<Component id="hitPreviousButton" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="hitNextButton" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="pageButtonsLabel" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="pagePreviousButton" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="pageNextButton" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="jSeparator1" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="sourceComboBox" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="pagesLabel" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="hitLabel" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="jSeparator2" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="pageCurLabel" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="pageOfLabel" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="hitCountLabel" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="pageTotalLabel" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="hitOfLabel" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="hitTotalLabel" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="hitButtonsLabel" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="126" max="32767" attributes="0"/>
<Component id="jScrollPane1" pref="23" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -123,7 +65,6 @@
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="ff" green="ff" red="ff" type="rgb"/>
</Property>
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[640, 29]"/>
</Property>
@ -143,256 +84,358 @@
<Dimension value="[2000, 2000]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[640, 29]"/>
<Dimension value="[600, 29]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new JTextPane(){&#xd;&#xa; public boolean getScrollableTracksViewportWidth() {&#xd;&#xa; return (getSize().width &lt; 400);&#xd;&#xa;}};"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JComboBox" name="sourceComboBox">
<Container class="javax.swing.JScrollPane" name="jScrollPane2">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new javax.swing.DefaultComboBoxModel&lt;org.sleuthkit.autopsy.keywordsearch.IndexedText&gt;()" type="code"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[150, 32767]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[150, 20]"/>
</Property>
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
<Property name="verticalScrollBarPolicy" type="int" value="21"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[150, 20]"/>
<Dimension value="[600, 100]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new javax.swing.JComboBox&lt;&gt;()"/>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;org.sleuthkit.autopsy.keywordsearch.IndexedText&gt;"/>
</AuxValues>
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="pageOfLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.pageOfLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="pageButtonsLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.pageButtonsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="pageTotalLabel">
<Properties>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.pageTotalLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="pagesLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.pagesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="pageNextButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/btn_step_forward.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.pageNextButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<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/>
</Border>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="disabledIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/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>
</Component>
<Component class="javax.swing.JButton" name="pagePreviousButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/btn_step_back.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.pagePreviousButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="actionCommand" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.pagePreviousButton.actionCommand" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<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/>
</Border>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="disabledIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/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>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="pageCurLabel">
<Properties>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.pageCurLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JSeparator" name="jSeparator1">
<Properties>
<Property name="orientation" type="int" value="1"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="hitLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.hitLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.hitLabel.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="hitButtonsLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.hitButtonsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="hitNextButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/btn_step_forward.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.hitNextButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<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/>
</Border>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="disabledIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/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>
<Property name="rolloverIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/btn_step_forward_hover.png"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="hitOfLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.hitOfLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="hitTotalLabel">
<Properties>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.hitTotalLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="hitPreviousButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/btn_step_back.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.hitPreviousButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<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/>
</Border>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="disabledIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/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>
<Property name="rolloverIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/btn_step_back_hover.png"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="hitCountLabel">
<Properties>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.hitCountLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JSeparator" name="jSeparator2">
<Properties>
<Property name="orientation" type="int" value="1"/>
</Properties>
</Component>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel1">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 0]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[600, 81]"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="600" max="32767" attributes="0"/>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="hitLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="hitCountLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="hitOfLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="hitTotalLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="hitButtonsLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="hitPreviousButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="hitNextButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="jSeparator2" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="pagesLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="pageCurLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="pageOfLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="pageTotalLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" min="-2" max="-2" attributes="0"/>
<Component id="pageButtonsLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="pagePreviousButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="pageNextButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="jSeparator1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="sourceComboBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="81" max="32767" attributes="0"/>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="2" attributes="0">
<Component id="hitPreviousButton" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="hitNextButton" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="pageButtonsLabel" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="pagePreviousButton" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="pageNextButton" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="jSeparator1" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="sourceComboBox" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="pagesLabel" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="hitLabel" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="jSeparator2" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="pageCurLabel" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="pageOfLabel" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="hitCountLabel" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="pageTotalLabel" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="hitOfLabel" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="hitTotalLabel" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="hitButtonsLabel" linkSize="1" alignment="2" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JComboBox" name="sourceComboBox">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new javax.swing.DefaultComboBoxModel&lt;org.sleuthkit.autopsy.keywordsearch.IndexedText&gt;()" type="code"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[150, 32767]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[150, 20]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[150, 20]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new javax.swing.JComboBox&lt;&gt;()"/>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;org.sleuthkit.autopsy.keywordsearch.IndexedText&gt;"/>
</AuxValues>
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="pageOfLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.pageOfLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="pageButtonsLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.pageButtonsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="pageTotalLabel">
<Properties>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.pageTotalLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="pagesLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.pagesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="pageNextButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/btn_step_forward.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.pageNextButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<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/>
</Border>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="disabledIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/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>
</Component>
<Component class="javax.swing.JButton" name="pagePreviousButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/btn_step_back.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.pagePreviousButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="actionCommand" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.pagePreviousButton.actionCommand" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<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/>
</Border>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="disabledIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/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>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="pageCurLabel">
<Properties>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.pageCurLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JSeparator" name="jSeparator1">
<Properties>
<Property name="orientation" type="int" value="1"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="hitLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.hitLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.hitLabel.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="hitButtonsLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.hitButtonsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="hitNextButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/btn_step_forward.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.hitNextButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<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/>
</Border>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="disabledIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/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>
<Property name="rolloverIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/btn_step_forward_hover.png"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="hitOfLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.hitOfLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="hitTotalLabel">
<Properties>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.hitTotalLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="hitPreviousButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/btn_step_back.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.hitPreviousButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<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/>
</Border>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="disabledIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/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>
<Property name="rolloverIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/btn_step_back_hover.png"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="hitCountLabel">
<Properties>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="ExtractedContentPanel.hitCountLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[18, 14]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JSeparator" name="jSeparator2">
<Properties>
<Property name="orientation" type="int" value="1"/>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -145,133 +145,140 @@ class ExtractedContentPanel extends javax.swing.JPanel {
copyMenuItem = new javax.swing.JMenuItem();
selectAllMenuItem = new javax.swing.JMenuItem();
jScrollPane1 = new javax.swing.JScrollPane();
extractedTextPane = new JTextPane(){
public boolean getScrollableTracksViewportWidth() {
return (getSize().width < 400);
}};
sourceComboBox = new javax.swing.JComboBox<>();
jLabel1 = new javax.swing.JLabel();
pageOfLabel = new javax.swing.JLabel();
pageButtonsLabel = new javax.swing.JLabel();
pageTotalLabel = new javax.swing.JLabel();
pagesLabel = new javax.swing.JLabel();
pageNextButton = new javax.swing.JButton();
pagePreviousButton = new javax.swing.JButton();
pageCurLabel = new javax.swing.JLabel();
jSeparator1 = new javax.swing.JSeparator();
hitLabel = new javax.swing.JLabel();
hitButtonsLabel = new javax.swing.JLabel();
hitNextButton = new javax.swing.JButton();
hitOfLabel = new javax.swing.JLabel();
hitTotalLabel = new javax.swing.JLabel();
hitPreviousButton = new javax.swing.JButton();
hitCountLabel = new javax.swing.JLabel();
jSeparator2 = new javax.swing.JSeparator();
extractedTextPane = new javax.swing.JTextPane();
jScrollPane2 = new javax.swing.JScrollPane();
jPanel1 = new javax.swing.JPanel();
sourceComboBox = new javax.swing.JComboBox<>();
jLabel1 = new javax.swing.JLabel();
pageOfLabel = new javax.swing.JLabel();
pageButtonsLabel = new javax.swing.JLabel();
pageTotalLabel = new javax.swing.JLabel();
pagesLabel = new javax.swing.JLabel();
pageNextButton = new javax.swing.JButton();
pagePreviousButton = new javax.swing.JButton();
pageCurLabel = new javax.swing.JLabel();
jSeparator1 = new javax.swing.JSeparator();
hitLabel = new javax.swing.JLabel();
hitButtonsLabel = new javax.swing.JLabel();
hitNextButton = new javax.swing.JButton();
hitOfLabel = new javax.swing.JLabel();
hitTotalLabel = new javax.swing.JLabel();
hitPreviousButton = new javax.swing.JButton();
hitCountLabel = new javax.swing.JLabel();
jSeparator2 = new javax.swing.JSeparator();
copyMenuItem.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.copyMenuItem.text")); // NOI18N
rightClickMenu.add(copyMenuItem);
copyMenuItem.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.copyMenuItem.text")); // NOI18N
rightClickMenu.add(copyMenuItem);
selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.selectAllMenuItem.text")); // NOI18N
rightClickMenu.add(selectAllMenuItem);
selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.selectAllMenuItem.text")); // NOI18N
rightClickMenu.add(selectAllMenuItem);
setPreferredSize(new java.awt.Dimension(717, 58));
setPreferredSize(new java.awt.Dimension(100, 58));
jScrollPane1.setBackground(new java.awt.Color(255, 255, 255));
jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
jScrollPane1.setPreferredSize(new java.awt.Dimension(640, 29));
jScrollPane1.setBackground(new java.awt.Color(255, 255, 255));
jScrollPane1.setPreferredSize(new java.awt.Dimension(640, 29));
extractedTextPane.setEditable(false);
extractedTextPane.setAutoscrolls(false);
extractedTextPane.setInheritsPopupMenu(true);
extractedTextPane.setMaximumSize(new java.awt.Dimension(2000, 2000));
extractedTextPane.setPreferredSize(new java.awt.Dimension(640, 29));
jScrollPane1.setViewportView(extractedTextPane);
extractedTextPane.setEditable(false);
extractedTextPane.setAutoscrolls(false);
extractedTextPane.setInheritsPopupMenu(true);
extractedTextPane.setMaximumSize(new java.awt.Dimension(2000, 2000));
extractedTextPane.setPreferredSize(new java.awt.Dimension(600, 29));
jScrollPane1.setViewportView(extractedTextPane);
sourceComboBox.setModel(new javax.swing.DefaultComboBoxModel<org.sleuthkit.autopsy.keywordsearch.IndexedText>());
sourceComboBox.setMaximumSize(new java.awt.Dimension(150, 32767));
sourceComboBox.setMinimumSize(new java.awt.Dimension(150, 20));
sourceComboBox.setPreferredSize(new java.awt.Dimension(150, 20));
jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
jScrollPane2.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
jScrollPane2.setPreferredSize(new java.awt.Dimension(600, 100));
jLabel1.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.jLabel1.text")); // NOI18N
jPanel1.setMinimumSize(new java.awt.Dimension(0, 0));
jPanel1.setPreferredSize(new java.awt.Dimension(600, 81));
pageOfLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageOfLabel.text")); // NOI18N
sourceComboBox.setModel(new javax.swing.DefaultComboBoxModel<org.sleuthkit.autopsy.keywordsearch.IndexedText>());
sourceComboBox.setMaximumSize(new java.awt.Dimension(150, 32767));
sourceComboBox.setMinimumSize(new java.awt.Dimension(150, 20));
sourceComboBox.setPreferredSize(new java.awt.Dimension(150, 20));
pageButtonsLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageButtonsLabel.text")); // NOI18N
jLabel1.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.jLabel1.text")); // NOI18N
pageTotalLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
pageTotalLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageTotalLabel.text")); // NOI18N
pageOfLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageOfLabel.text")); // NOI18N
pagesLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pagesLabel.text")); // NOI18N
pageButtonsLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageButtonsLabel.text")); // NOI18N
pageNextButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward.png"))); // NOI18N
pageNextButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageNextButton.text")); // NOI18N
pageNextButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
pageNextButton.setBorderPainted(false);
pageNextButton.setContentAreaFilled(false);
pageNextButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward_disabled.png"))); // NOI18N
pageNextButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
pageNextButton.setPreferredSize(new java.awt.Dimension(23, 23));
pageTotalLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
pageTotalLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageTotalLabel.text")); // NOI18N
pagePreviousButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back.png"))); // NOI18N
pagePreviousButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pagePreviousButton.text")); // NOI18N
pagePreviousButton.setActionCommand(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pagePreviousButton.actionCommand")); // NOI18N
pagePreviousButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
pagePreviousButton.setBorderPainted(false);
pagePreviousButton.setContentAreaFilled(false);
pagePreviousButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back_disabled.png"))); // NOI18N
pagePreviousButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
pagesLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pagesLabel.text")); // NOI18N
pageCurLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
pageCurLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageCurLabel.text")); // NOI18N
pageNextButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward.png"))); // NOI18N
pageNextButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageNextButton.text")); // NOI18N
pageNextButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
pageNextButton.setBorderPainted(false);
pageNextButton.setContentAreaFilled(false);
pageNextButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward_disabled.png"))); // NOI18N
pageNextButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
pageNextButton.setPreferredSize(new java.awt.Dimension(23, 23));
jSeparator1.setOrientation(javax.swing.SwingConstants.VERTICAL);
pagePreviousButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back.png"))); // NOI18N
pagePreviousButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pagePreviousButton.text")); // NOI18N
pagePreviousButton.setActionCommand(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pagePreviousButton.actionCommand")); // NOI18N
pagePreviousButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
pagePreviousButton.setBorderPainted(false);
pagePreviousButton.setContentAreaFilled(false);
pagePreviousButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back_disabled.png"))); // NOI18N
pagePreviousButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
hitLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitLabel.text")); // NOI18N
hitLabel.setToolTipText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitLabel.toolTipText")); // NOI18N
pageCurLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
pageCurLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageCurLabel.text")); // NOI18N
hitButtonsLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitButtonsLabel.text")); // NOI18N
jSeparator1.setOrientation(javax.swing.SwingConstants.VERTICAL);
hitNextButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward.png"))); // NOI18N
hitNextButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitNextButton.text")); // NOI18N
hitNextButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
hitNextButton.setBorderPainted(false);
hitNextButton.setContentAreaFilled(false);
hitNextButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward_disabled.png"))); // NOI18N
hitNextButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
hitNextButton.setPreferredSize(new java.awt.Dimension(23, 23));
hitNextButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward_hover.png"))); // NOI18N
hitLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitLabel.text")); // NOI18N
hitLabel.setToolTipText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitLabel.toolTipText")); // NOI18N
hitOfLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitOfLabel.text")); // NOI18N
hitButtonsLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitButtonsLabel.text")); // NOI18N
hitTotalLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
hitTotalLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitTotalLabel.text")); // NOI18N
hitTotalLabel.setMaximumSize(new java.awt.Dimension(18, 14));
hitTotalLabel.setMinimumSize(new java.awt.Dimension(18, 14));
hitTotalLabel.setPreferredSize(new java.awt.Dimension(18, 14));
hitNextButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward.png"))); // NOI18N
hitNextButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitNextButton.text")); // NOI18N
hitNextButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
hitNextButton.setBorderPainted(false);
hitNextButton.setContentAreaFilled(false);
hitNextButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward_disabled.png"))); // NOI18N
hitNextButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
hitNextButton.setPreferredSize(new java.awt.Dimension(23, 23));
hitNextButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward_hover.png"))); // NOI18N
hitPreviousButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back.png"))); // NOI18N
hitPreviousButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitPreviousButton.text")); // NOI18N
hitPreviousButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
hitPreviousButton.setBorderPainted(false);
hitPreviousButton.setContentAreaFilled(false);
hitPreviousButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back_disabled.png"))); // NOI18N
hitPreviousButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
hitPreviousButton.setPreferredSize(new java.awt.Dimension(23, 23));
hitPreviousButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back_hover.png"))); // NOI18N
hitOfLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitOfLabel.text")); // NOI18N
hitCountLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
hitCountLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitCountLabel.text")); // NOI18N
hitCountLabel.setMaximumSize(new java.awt.Dimension(18, 14));
hitCountLabel.setMinimumSize(new java.awt.Dimension(18, 14));
hitCountLabel.setPreferredSize(new java.awt.Dimension(18, 14));
hitTotalLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
hitTotalLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitTotalLabel.text")); // NOI18N
hitTotalLabel.setMaximumSize(new java.awt.Dimension(18, 14));
hitTotalLabel.setMinimumSize(new java.awt.Dimension(18, 14));
hitTotalLabel.setPreferredSize(new java.awt.Dimension(18, 14));
jSeparator2.setOrientation(javax.swing.SwingConstants.VERTICAL);
hitPreviousButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back.png"))); // NOI18N
hitPreviousButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitPreviousButton.text")); // NOI18N
hitPreviousButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
hitPreviousButton.setBorderPainted(false);
hitPreviousButton.setContentAreaFilled(false);
hitPreviousButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back_disabled.png"))); // NOI18N
hitPreviousButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
hitPreviousButton.setPreferredSize(new java.awt.Dimension(23, 23));
hitPreviousButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back_hover.png"))); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
hitCountLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
hitCountLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitCountLabel.text")); // NOI18N
hitCountLabel.setMaximumSize(new java.awt.Dimension(18, 14));
hitCountLabel.setMinimumSize(new java.awt.Dimension(18, 14));
hitCountLabel.setPreferredSize(new java.awt.Dimension(18, 14));
jSeparator2.setOrientation(javax.swing.SwingConstants.VERTICAL);
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 600, Short.MAX_VALUE)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(hitLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
@ -308,14 +315,15 @@ class ExtractedContentPanel extends javax.swing.JPanel {
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(sourceComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()))
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 81, Short.MAX_VALUE)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
.addComponent(hitPreviousButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel1)
.addComponent(hitNextButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
@ -334,13 +342,28 @@ class ExtractedContentPanel extends javax.swing.JPanel {
.addComponent(hitOfLabel)
.addComponent(hitTotalLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(hitButtonsLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 126, Short.MAX_VALUE))
);
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
);
layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {hitButtonsLabel, hitCountLabel, hitLabel, hitNextButton, hitOfLabel, hitPreviousButton, hitTotalLabel, jLabel1, jSeparator1, jSeparator2, pageButtonsLabel, pageCurLabel, pageNextButton, pageOfLabel, pagePreviousButton, pageTotalLabel, pagesLabel, sourceComboBox});
jPanel1Layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {hitButtonsLabel, hitCountLabel, hitLabel, hitNextButton, hitOfLabel, hitPreviousButton, hitTotalLabel, jLabel1, jSeparator1, jSeparator2, pageButtonsLabel, pageCurLabel, pageNextButton, pageOfLabel, pagePreviousButton, pageTotalLabel, pagesLabel, sourceComboBox});
}// </editor-fold>//GEN-END:initComponents
jScrollPane2.setViewportView(jPanel1);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 100, Short.MAX_VALUE)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 100, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 46, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 23, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JMenuItem copyMenuItem;
private javax.swing.JTextPane extractedTextPane;
@ -352,7 +375,9 @@ class ExtractedContentPanel extends javax.swing.JPanel {
private javax.swing.JButton hitPreviousButton;
private javax.swing.JLabel hitTotalLabel;
private javax.swing.JLabel jLabel1;
private javax.swing.JPanel jPanel1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JSeparator jSeparator1;
private javax.swing.JSeparator jSeparator2;
private javax.swing.JLabel pageButtonsLabel;

View File

@ -125,7 +125,10 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
}
}
@NbBundle.Messages("GlobalEditListPanel.editKeyword.title=Edit Keyword")
@NbBundle.Messages({"GlobalEditListPanel.editKeyword.title=Edit Keyword",
"GlobalEditListPanel.warning.title=Warning",
"GlobalEditListPanel.warning.text=Boundary characters ^ and $ do not match word boundaries. Consider\nreplacing with an explicit list of boundary characters, such as [ \\.,]"})
/**
* Adds keywords to a keyword list, returns true if at least one keyword was
* successfully added and no duplicates were found.
@ -151,6 +154,7 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
dupeCount = 0;
badCount = 0;
keywordsToRedisplay = "";
boolean displayedBoundaryWarning = false;
if (!dialog.getKeywords().isEmpty()) {
@ -164,6 +168,19 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
dupeCount++;
continue;
}
// Check if it is a regex and starts or ends with a boundary character
if (( ! displayedBoundaryWarning) && dialog.isKeywordRegex()) {
if(newWord.startsWith("^") ||
(newWord.endsWith("$") && ! newWord.endsWith("\\$"))) {
KeywordSearchUtil.displayDialog(NbBundle.getMessage(this.getClass(), "GlobalEditListPanel.warning.title"),
NbBundle.getMessage(this.getClass(), "GlobalEditListPanel.warning.text"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);
// Only display the warning once
displayedBoundaryWarning = true;
}
}
//check if valid
boolean valid = true;

View File

@ -27,6 +27,8 @@ import org.apache.solr.common.SolrInputDocument;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.healthmonitor.EnterpriseHealthMonitor;
import org.sleuthkit.autopsy.healthmonitor.TimingMetric;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.keywordsearch.Chunker.Chunk;
import org.sleuthkit.datamodel.AbstractFile;
@ -235,7 +237,9 @@ class Ingester {
try {
//TODO: consider timeout thread, or vary socket timeout based on size of indexed content
TimingMetric metric = EnterpriseHealthMonitor.getTimingMetric("Solr: Index chunk");
solrServer.addDocument(updateDoc);
EnterpriseHealthMonitor.submitTimingMetric(metric);
uncommitedIngests = true;
} catch (KeywordSearchModuleException | NoOpenCoreException ex) {

View File

@ -170,10 +170,13 @@ final class RegexQuery implements KeywordSearchQuery {
*/
// We construct the query by surrounding it with slashes (to indicate it is
// a regular expression search) and .* as anchors (if the query doesn't
// already have them).
// already have them). We do not add .* if there is a boundary character.
boolean skipWildcardPrefix = queryStringContainsWildcardPrefix || getQueryString().startsWith("^");
boolean skipWildcardSuffix = queryStringContainsWildcardSuffix ||
(getQueryString().endsWith("$") && ( ! getQueryString().endsWith("\\$")));
solrQuery.setQuery((field == null ? Server.Schema.CONTENT_STR.toString() : field) + ":/"
+ (queryStringContainsWildcardPrefix ? "" : ".*") + getQueryString()
+ (queryStringContainsWildcardSuffix ? "" : ".*") + "/");
+ (skipWildcardPrefix ? "" : ".*") + getQueryString()
+ (skipWildcardSuffix ? "" : ".*") + "/");
// Set the fields we want to have returned by the query.
solrQuery.setFields(Server.Schema.CONTENT_STR.toString(), Server.Schema.ID.toString(), Server.Schema.CHUNK_SIZE.toString());

View File

@ -70,6 +70,8 @@ import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.healthmonitor.EnterpriseHealthMonitor;
import org.sleuthkit.autopsy.healthmonitor.TimingMetric;
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchServiceException;
import org.sleuthkit.datamodel.Content;
@ -708,7 +710,9 @@ public class Server {
if (null == currentCore) {
throw new NoOpenCoreException();
}
TimingMetric metric = EnterpriseHealthMonitor.getTimingMetric("Solr: Index chunk");
currentCore.addDocument(doc);
EnterpriseHealthMonitor.submitTimingMetric(metric);
} finally {
currentCoreLock.readLock().unlock();
}
@ -773,7 +777,9 @@ public class Server {
IndexingServerProperties properties = getMultiUserServerProperties(theCase.getCaseDirectory());
currentSolrServer = new HttpSolrServer("http://" + properties.getHost() + ":" + properties.getPort() + "/solr"); //NON-NLS
}
TimingMetric metric = EnterpriseHealthMonitor.getTimingMetric("Solr: Connectivity check");
connectToSolrServer(currentSolrServer);
EnterpriseHealthMonitor.submitTimingMetric(metric);
} catch (SolrServerException | IOException ex) {
throw new KeywordSearchModuleException(NbBundle.getMessage(Server.class, "Server.connect.exception.msg", ex.getLocalizedMessage()), ex);
@ -1315,11 +1321,13 @@ public class Server {
* @throws IOException
*/
void connectToSolrServer(HttpSolrServer solrServer) throws SolrServerException, IOException {
TimingMetric metric = EnterpriseHealthMonitor.getTimingMetric("Solr: Connectivity check");
CoreAdminRequest statusRequest = new CoreAdminRequest();
statusRequest.setCoreName( null );
statusRequest.setAction( CoreAdminParams.CoreAdminAction.STATUS );
statusRequest.setIndexInfoNeeded(false);
statusRequest.process(solrServer);
EnterpriseHealthMonitor.submitTimingMetric(metric);
}
/**

View File

@ -39,6 +39,11 @@ Substring match should be used where the search term is just part of a word, or
Regex match can be used to search for a specific pattern. Regular expressions are supported using Lucene Regex Syntax which is documented here: https://www.elastic.co/guide/en/elasticsearch/reference/1.6/query-dsl-regexp-query.html#regexp-syntax. Wildcards are automatically added to the beginning and end of the regular expressions to ensure all matches are found. Additionally, the resulting hits are split on common token separator boundaries (e.g. space, newline, colon, exclamation point etc.) to make the resulting keyword hit more amenable to highlighting.
<b>Note:</b> Since Autopsy 4.4, boundary characters ('^' and '$') no longer work as word boundaries. Previously a search for "^[0-9]{5}$" would return all five
digit strings surrounded by some type of non-word characters. For example, "The number 12345 is.." would contain a match, while "123456789 people" would not. This was because the regex
was compared against each "word" in the document. In newer versions, the text is not split into words internally so this type of search no longer works. To get similar results, replace the
boundary characters with the specific characters that should represent a word break. For example, "^[0-9]{5}$" could become "[ \.\-\,][0-9]{5}[ \.\-\,]".
There is some validation on the regex but it's best to test on a sample image to make sure your regexes are correct and working as expected. One simple way to test is by creating a sample text file that your expression should match, ingesting it as a \ref ds_log "Logical File Set" and then running the regex query.
> In the year 1885 in an article titled Current Notes, the quick brown fox first jumped over the lazy dog.

View File

@ -34,7 +34,7 @@ To open a case, either:
"Open Recent Case" will always bring up a screen allowing you to select one of the recently opened cases. "Open Case" will do one of two things;
- If multi-user cases are not enabled, it will bring up a file chooser that can be used to browse to the ".aut" file in the case directory of the desired case
- If multi-user case are enabled, it will bring up the multi-user case selection screen. This uses the coordination services to find a list of multi-user cases. If needed, the "Open Single-User Case" button can be used to bring up the normal file chooser. The following shows the multi-user case selection screen:
- If multi-user cases are enabled, it will bring up the multi-user case selection screen. This uses the coordination services to find a list of multi-user cases. If needed, the "Open Single-User Case" button can be used to bring up the normal file chooser. The multi-user case selection screen has a \ref quick_search feature which can be used to quickly find a case in the table. The following shows the multi-user case selection screen:
\image html multi_user_case_select.png

View File

@ -20,6 +20,8 @@ The middle column displays each account, its device and type, and the number of
Selecting an account in the middle column will bring up the messages for that account in the right hand column. Here data about each message is displayed in the top section, and the messages itself can be seen in the bottom section (if applicable).
The middle column and the right hand column both have a \ref quick_search feature which can be used to quickly find a visible item in their section's table.
\image html cvt_messages.png
*/

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -39,6 +39,7 @@ The following topics are available here:
- \subpage tree_viewer_page
- \subpage result_viewer_page
- \subpage content_viewer_page
- \subpage quick_search
- \subpage image_gallery_page
- \subpage file_search_page
- \subpage ad_hoc_keyword_search_page

View File

@ -0,0 +1,24 @@
/*! \page quick_search Quick Search
The quick search feature allows you to search within the data on a panel for a given string, it will not search data in hidden columns or collapsed nodes.
How to use it
-----
In order to use the search you need to select any item in the area you wish to search, and start typing. If quick search is available in the area you have selected a search field will appear in the bottom left hand corner of the area. As you type the string you are searching for it will auto-update to select one of the results which matches your string. You can switch between the results which match the string you have typed with the up and down keys. The search does not support the use of regular expressions but will match against any sub-sting in the fields it searches, not just at the beginning of the field.
\image html quick_search_result.PNG
Configuration
-----
By default the search will match against the data in all fields which are in the currently selected area. The search will also ignore case by default. If you want to change either of these default behaviors you can click the magnifying glass with the down arrow icon and configure which columns will be searched as well as if the search should ignore case.
\image html quick_search_configuration.PNG
Where it can be used
-----
- The \ref tree_viewer_page "tree viewer"
- The \ref result_viewer_page "table view"
- The \ref case_open "open multi-user case panel"
- The \ref timeline_page tools table view
- The \ref communications_page "Communication Visualization Tool's" browse panel
- The \ref communications_page "Communication Visualization Tool's" message panel
*/

View File

@ -59,6 +59,8 @@ If you are viewing files from the Views and Results nodes, you can right-click o
If you want to search for single keywords, then you can use the search box in the upper right of the program. The results will be shown in a table in the upper right.
The tree on the left as well as the table on the right have a \ref quick_search feature which can be used to quickly find a visible node.
You can tag (bookmark) arbitrary files so that you can more quickly find them later or so that you can include them specifically in a report.
\subsection s2a Ingest Inbox

View File

@ -69,6 +69,7 @@ The __Counts View__ shows a stacked bar chart. Use this type of graph to show ho
The __Details View__ shows individual or groups of related events. Date/time is represented horizontally along the x-axis, but the vertical axis does not represent any specific units. You would use this interface to answer questions about what specific events happened in a given time frame or what events occurred before or after a given event. You would generally use this type of interface after using the Counts View to identify a period of time that you wanted details on. There can be a lot of details in this view and we have introduced zooming concepts, as described in the next section, to help with this.
The table on the bottom left hand side of the panel has a \ref quick_search feature which can be used to quickly find a node in the table.
Visualization settings
----------------------