Merge branch '3139_cr_hashes' into 3141_addHashes

Conflicts:
	Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddContentToHashDbAction.java
	Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java
	Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java
	Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java
This commit is contained in:
Ann Priestman 2017-11-17 12:25:56 -05:00
commit ff3f620b00
84 changed files with 3641 additions and 2980 deletions

View File

@ -244,6 +244,46 @@
<code-name-base>org.netbeans.libs.junit4</code-name-base> <code-name-base>org.netbeans.libs.junit4</code-name-base>
<compile-dependency/> <compile-dependency/>
</test-dependency> </test-dependency>
<test-dependency>
<code-name-base>org.netbeans.modules.jellytools.java</code-name-base>
<compile-dependency/>
</test-dependency>
<test-dependency>
<code-name-base>org.netbeans.modules.jellytools.platform</code-name-base>
<compile-dependency/>
</test-dependency>
<test-dependency>
<code-name-base>org.netbeans.modules.jemmy</code-name-base>
<compile-dependency/>
</test-dependency>
<test-dependency>
<code-name-base>org.netbeans.modules.nbjunit</code-name-base>
<compile-dependency/>
</test-dependency>
</test-type>
<test-type>
<name>qa-functional</name>
<test-dependency>
<code-name-base>org.netbeans.libs.junit4</code-name-base>
<compile-dependency/>
</test-dependency>
<test-dependency>
<code-name-base>org.netbeans.modules.jellytools.java</code-name-base>
<compile-dependency/>
</test-dependency>
<test-dependency>
<code-name-base>org.netbeans.modules.jellytools.platform</code-name-base>
<compile-dependency/>
</test-dependency>
<test-dependency>
<code-name-base>org.netbeans.modules.jemmy</code-name-base>
<compile-dependency/>
</test-dependency>
<test-dependency>
<code-name-base>org.netbeans.modules.nbjunit</code-name-base>
<recursive/>
<compile-dependency/>
</test-dependency>
</test-type> </test-type>
</test-dependencies> </test-dependencies>
<public-packages> <public-packages>
@ -269,6 +309,7 @@
<package>org.sleuthkit.autopsy.events</package> <package>org.sleuthkit.autopsy.events</package>
<package>org.sleuthkit.autopsy.externalresults</package> <package>org.sleuthkit.autopsy.externalresults</package>
<package>org.sleuthkit.autopsy.filesearch</package> <package>org.sleuthkit.autopsy.filesearch</package>
<package>org.sleuthkit.autopsy.guiutils</package>
<package>org.sleuthkit.autopsy.ingest</package> <package>org.sleuthkit.autopsy.ingest</package>
<package>org.sleuthkit.autopsy.keywordsearchservice</package> <package>org.sleuthkit.autopsy.keywordsearchservice</package>
<package>org.sleuthkit.autopsy.menuactions</package> <package>org.sleuthkit.autopsy.menuactions</package>

View File

@ -1,29 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 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.casemodule;
import javax.swing.JDialog;
/**
* Interface for startup window implementations
*/
public interface AutoIngestCasePanelInterface {
public void addWindowStateListener(JDialog parent);
}

View File

@ -1,10 +1,10 @@
CTL_AddImage=Add Data Source... CTL_AddImage=Add Data Source
CTL_AddImageButton=Add Data Source CTL_AddImageButton=Add Data Source
CTL_CaseCloseAct=Close Case CTL_CaseCloseAct=Close Case
CTL_CaseNewAction=New Case... CTL_CaseNewAction=New Case
CTL_CasePropertiesAction=Case Properties... CTL_CasePropertiesAction=Case Properties
CTL_CaseDeleteAction=Delete Case CTL_CaseDeleteAction=Delete Case
CTL_OpenAction=Open Case... CTL_CaseOpenAction=Open Case
Menu/Case/OpenRecentCase=Open Recent Case Menu/Case/OpenRecentCase=Open Recent Case
CTL_CaseDeleteAction=Delete Case CTL_CaseDeleteAction=Delete Case
OpenIDE-Module-Name=Case OpenIDE-Module-Name=Case
@ -210,11 +210,32 @@ CasePropertiesPanel.lbDbName.text=Database Name:
CasePropertiesPanel.lbDbType.text=Case Type: CasePropertiesPanel.lbDbType.text=Case Type:
CasePropertiesPanel.caseNumberLabel.text=Case Number: CasePropertiesPanel.caseNumberLabel.text=Case Number:
LocalDiskPanel.changeDatabasePathCheckbox.text=Update case to use VHD file upon completion LocalDiskPanel.changeDatabasePathCheckbox.text=Update case to use VHD file upon completion
CueBannerPanel.openAutoIngestCaseButton.text= CueBannerPanel.openMultiUserCaseButton.text=
CueBannerPanel.openExistingCaseButton.text= CueBannerPanel.openExistingCaseButton.text=
CueBannerPanel.openRecentCaseButton.text= CueBannerPanel.openRecentCaseButton.text=
CueBannerPanel.createNewCaseButton.text= CueBannerPanel.createNewCaseButton.text=
CueBannerPanel.createNewCaseLabel.text=Create New Case CueBannerPanel.createNewCaseLabel.text=Create New Case
CueBannerPanel.openRecentCaseLabel.text=Open Recent Case CueBannerPanel.openRecentCaseLabel.text=Open Recent Case
CueBannerPanel.openExistingCaseLabel.text=Open Existing Case CueBannerPanel.openExistingCaseLabel.text=Open Existing Case
CueBannerPanel.openAutoIngestCaseLabel.text=Open Auto Ingest Case CueBannerPanel.openMultiUserCaseLabel.text=Open Multi-User Case
ReviewModeCasePanel.cannotOpenCase=Cannot Open Case
ReviewModeCasePanel.casePathNotFound=Case path not found
ReviewModeCasePanel.caseIsLocked=Single-user case is locked.
ReviewModeCasePanel.CaseHeaderText=Case
ReviewModeCasePanel.CreatedTimeHeaderText=Created Time
ReviewModeCasePanel.StatusIconHeaderText=Status
ReviewModeCasePanel.OutputFolderHeaderText=Output Folder
ReviewModeCasePanel.LastAccessedTimeHeaderText=Last Accessed Time
ReviewModeCasePanel.MetadataFileHeaderText=Metadata File
OpenMultiUserCasePanel.jLabel1.text=Recent Cases
OpenMultiUserCasePanel.openButton.text=Open
OpenMultiUserCasePanel.cancelButton.text=Cancel
MultiUserCasesPanel.rbWeeks.text=Weeks
MultiUserCasesPanel.rbDays.text=Days
MultiUserCasesPanel.bnShowLog.toolTipText=Display case log file for selected case
MultiUserCasesPanel.bnShowLog.text=&Show Auto Ingest Case Log
MultiUserCasesPanel.rbAllCases.text=Everything
MultiUserCasesPanel.bnRefresh.text=&Refresh
MultiUserCasesPanel.bnOpen.text=&Open
MultiUserCasesPanel.rbGroupLabel.text=Show cases accessed in the last 10:
MultiUserCasesPanel.rbMonths.text=Months

View File

@ -1,9 +1,9 @@
CTL_AddImageButton=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u8ffd\u52a0 CTL_AddImageButton=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u8ffd\u52a0
CTL_CaseCloseAct=\u30b1\u30fc\u30b9\u3092\u9589\u3058\u308b CTL_CaseCloseAct=\u30b1\u30fc\u30b9\u3092\u9589\u3058\u308b
CTL_CaseNewAction=\u65b0\u898f\u30b1\u30fc\u30b9... CTL_CaseNewAction=\u65b0\u898f\u30b1\u30fc\u30b9
CTL_CasePropertiesAction=\u30b1\u30fc\u30b9\u30d7\u30ed\u30d1\u30c6\u30a3... CTL_CasePropertiesAction=\u30b1\u30fc\u30b9\u30d7\u30ed\u30d1\u30c6\u30a3
CTL_CaseDeleteAction=\u30b1\u30fc\u30b9\u3092\u524a\u9664 CTL_CaseDeleteAction=\u30b1\u30fc\u30b9\u3092\u524a\u9664
CTL_OpenAction=\u30b1\u30fc\u30b9\u3092\u958b\u304f... CTL_CaseOpenAction=\u30b1\u30fc\u30b9\u3092\u958b\u304f
Menu/Case/OpenRecentCase=\u6700\u8fd1\u958b\u3044\u305f\u30b1\u30fc\u30b9\u3092\u958b\u304f Menu/Case/OpenRecentCase=\u6700\u8fd1\u958b\u3044\u305f\u30b1\u30fc\u30b9\u3092\u958b\u304f
CTL_CaseDeleteAction=\u30b1\u30fc\u30b9\u3092\u524a\u9664 CTL_CaseDeleteAction=\u30b1\u30fc\u30b9\u3092\u524a\u9664
OpenIDE-Module-Name=\u30b1\u30fc\u30b9 OpenIDE-Module-Name=\u30b1\u30fc\u30b9
@ -194,3 +194,6 @@ CueBannerPanel.createNewCaseLabel.text=\u65b0\u898f\u30b1\u30fc\u30b9\u3092\u4f5
CueBannerPanel.openRecentCaseLabel.text=\u6700\u8fd1\u958b\u3044\u305f\u30b1\u30fc\u30b9\u3092\u958b\u304f CueBannerPanel.openRecentCaseLabel.text=\u6700\u8fd1\u958b\u3044\u305f\u30b1\u30fc\u30b9\u3092\u958b\u304f
CueBannerPanel.openExistingCaseLabel.text=\u65e2\u5b58\u30b1\u30fc\u30b9\u3092\u958b\u304f CueBannerPanel.openExistingCaseLabel.text=\u65e2\u5b58\u30b1\u30fc\u30b9\u3092\u958b\u304f
CueBannerPanel.openAutoIngestCaseLabel.text=\u65e2\u5b58\u30b1\u30fc\u30b9\u3092\u958b\u304f CueBannerPanel.openAutoIngestCaseLabel.text=\u65e2\u5b58\u30b1\u30fc\u30b9\u3092\u958b\u304f
OpenMultiUserCasePanel.openButton.text=\u958b\u304f
OpenMultiUserCasePanel.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb
OpenMultiUserCasePanel.jLabel1.text=\u6700\u8fd1\u958b\u3044\u305f\u30d5\u30a1\u30a4\u30eb

View File

@ -33,7 +33,6 @@ import org.openide.util.HelpCtx;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.openide.util.actions.CallableSystemAction; import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
/** /**
@ -45,13 +44,16 @@ import org.sleuthkit.autopsy.coreutils.Logger;
final class CaseDeleteAction extends CallableSystemAction { final class CaseDeleteAction extends CallableSystemAction {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(CaseDeleteAction.class.getName()); private static final Logger LOGGER = Logger.getLogger(CaseDeleteAction.class.getName());
CaseDeleteAction() { CaseDeleteAction() {
putValue(Action.NAME, NbBundle.getMessage(CaseDeleteAction.class, "CTL_CaseDeleteAction")); putValue(Action.NAME, NbBundle.getMessage(CaseDeleteAction.class, "CTL_CaseDeleteAction"));
this.setEnabled(false); this.setEnabled(false);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), (PropertyChangeEvent evt) -> { Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), (PropertyChangeEvent evt) -> {
setEnabled(null != evt.getNewValue() && UserPreferences.getMode() != UserPreferences.SelectedMode.REVIEW); /*
* A value of 'null' signifies that there is no case open.
*/
setEnabled(null != evt.getNewValue());
}); });
} }
@ -93,7 +95,7 @@ final class CaseDeleteAction extends CallableSystemAction {
try { try {
get(); get();
} catch (InterruptedException | ExecutionException ex) { } catch (InterruptedException | ExecutionException ex) {
logger.log(Level.SEVERE, String.format("Failed to delete case %s at %s", caseName, caseDirectory), ex); LOGGER.log(Level.SEVERE, String.format("Failed to delete case %s at %s", caseName, caseDirectory), ex);
JOptionPane.showMessageDialog( JOptionPane.showMessageDialog(
null, null,
Bundle.Case_deleteCaseFailureMessageBox_message(ex.getLocalizedMessage()), Bundle.Case_deleteCaseFailureMessageBox_message(ex.getLocalizedMessage()),
@ -108,7 +110,7 @@ final class CaseDeleteAction extends CallableSystemAction {
}.execute(); }.execute();
} }
} catch (IllegalStateException ex) { } catch (IllegalStateException ex) {
logger.log(Level.SEVERE, "Case delete action called with no current case", ex); LOGGER.log(Level.SEVERE, "Case delete action called with no current case", ex);
} }
} }

View File

@ -141,7 +141,7 @@ public final class CaseOpenAction extends CallableSystemAction implements Action
@Override @Override
public String getName() { public String getName() {
return NbBundle.getMessage(CaseOpenAction.class, "CTL_OpenAction"); return NbBundle.getMessage(CaseOpenAction.class, "CTL_CaseOpenAction");
} }
@Override @Override

View File

@ -0,0 +1,91 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 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.casemodule;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JDialog;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionRegistration;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.core.UserPreferences;
/**
* The action associated with the Open Multi-User Case menu item via the
* layer.xml file.
*
* This action should only be invoked in the event dispatch thread (EDT).
*/
@ActionID(category = "Case", id = "org.sleuthkit.autopsy.casemodule.CaseOpenMultiUserAction")
@ActionReference(path = "Menu/Case", position = 102)
@ActionRegistration(displayName = "#CTL_CaseOpenMultiUserAction", lazy = false)
@NbBundle.Messages({"CTL_CaseOpenMultiUserAction=Open Multi-User Case"})
public final class CaseOpenMultiUserAction extends CallableSystemAction implements ActionListener {
private static final long serialVersionUID = 1L;
private static JDialog multiUserCaseWindow;
private static final String DISPLAY_NAME = Bundle.CTL_CaseOpenMultiUserAction();
public CaseOpenMultiUserAction() {}
@Override
public boolean isEnabled() {
return UserPreferences.getIsMultiUserModeEnabled();
}
/**
* Pops up a case selection panel to allow the user to select a multi-user
* case to open.
*
* @param event The action event.
*/
@Override
public void actionPerformed(ActionEvent event) {
if(multiUserCaseWindow == null) {
multiUserCaseWindow = MultiUserCasesDialog.getInstance();
}
multiUserCaseWindow.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
multiUserCaseWindow.setVisible(true);
}
@Override
public void performAction() {
actionPerformed(null);
}
@Override
public String getName() {
return DISPLAY_NAME;
}
@Override
public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP;
}
@Override
public boolean asynchronous() {
return false; // run on edt
}
}

View File

@ -28,14 +28,14 @@
<Component id="createNewCaseButton" alignment="2" min="-2" max="-2" attributes="1"/> <Component id="createNewCaseButton" alignment="2" min="-2" max="-2" attributes="1"/>
<Component id="openRecentCaseButton" alignment="2" min="-2" pref="70" max="-2" attributes="1"/> <Component id="openRecentCaseButton" alignment="2" min="-2" pref="70" max="-2" attributes="1"/>
<Component id="openExistingCaseButton" alignment="2" min="-2" max="-2" attributes="1"/> <Component id="openExistingCaseButton" alignment="2" min="-2" max="-2" attributes="1"/>
<Component id="openAutoIngestCaseButton" alignment="2" min="-2" max="-2" attributes="1"/> <Component id="openMultiUserCaseButton" alignment="2" min="-2" max="-2" attributes="1"/>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="createNewCaseLabel" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="createNewCaseLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="openRecentCaseLabel" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="openRecentCaseLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="openExistingCaseLabel" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="openExistingCaseLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="openAutoIngestCaseLabel" min="-2" max="-2" attributes="0"/> <Component id="openMultiUserCaseLabel" min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
<Component id="closeButton" alignment="1" min="-2" pref="73" max="-2" attributes="0"/> <Component id="closeButton" alignment="1" min="-2" pref="73" max="-2" attributes="0"/>
@ -66,9 +66,9 @@
</Group> </Group>
<EmptySpace max="32767" attributes="0"/> <EmptySpace max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="openAutoIngestCaseButton" alignment="1" min="-2" pref="58" max="-2" attributes="0"/> <Component id="openMultiUserCaseButton" alignment="1" min="-2" pref="58" max="-2" attributes="0"/>
<Group type="102" alignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0">
<Component id="openAutoIngestCaseLabel" min="-2" max="-2" attributes="0"/> <Component id="openMultiUserCaseLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="20" max="-2" attributes="0"/> <EmptySpace min="-2" pref="20" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
@ -216,13 +216,13 @@
<Property name="orientation" type="int" value="1"/> <Property name="orientation" type="int" value="1"/>
</Properties> </Properties>
</Component> </Component>
<Component class="javax.swing.JButton" name="openAutoIngestCaseButton"> <Component class="javax.swing.JButton" name="openMultiUserCaseButton">
<Properties> <Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor"> <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/casemodule/btn_icon_open_existing.png"/> <Image iconType="3" name="/org/sleuthkit/autopsy/casemodule/btn_icon_open_existing.png"/>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CueBannerPanel.openAutoIngestCaseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CueBannerPanel.openMultiUserCaseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="null" type="code"/> <Connection code="null" type="code"/>
@ -237,18 +237,18 @@
</Property> </Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="openAutoIngestCaseButtonActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="openMultiUserCaseButtonActionPerformed"/>
</Events> </Events>
</Component> </Component>
<Component class="javax.swing.JLabel" name="openAutoIngestCaseLabel"> <Component class="javax.swing.JLabel" name="openMultiUserCaseLabel">
<Properties> <Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor"> <Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true"> <FontInfo relative="true">
<Font bold="false" component="openAutoIngestCaseLabel" property="font" relativeSize="false" size="13"/> <Font bold="false" component="openMultiUserCaseLabel" property="font" relativeSize="false" size="13"/>
</FontInfo> </FontInfo>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CueBannerPanel.openAutoIngestCaseLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CueBannerPanel.openMultiUserCaseLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
</Component> </Component>

View File

@ -26,14 +26,11 @@ import java.awt.event.KeyEvent;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JDialog; import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.KeyStroke; import javax.swing.KeyStroke;
import org.openide.util.Lookup; import org.openide.util.Lookup;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.windows.WindowManager; import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.AutoIngestCasePanelInterface;
import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
/* /*
* The panel in the default Autopsy startup window. * The panel in the default Autopsy startup window.
@ -41,14 +38,11 @@ import org.sleuthkit.autopsy.coreutils.NetworkUtils;
public class CueBannerPanel extends javax.swing.JPanel { public class CueBannerPanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final String LOCAL_HOST_NAME = NetworkUtils.getLocalHostName();
private static final String REVIEW_MODE_TITLE = "Cases" + " (" + LOCAL_HOST_NAME + ")";
/* /*
* This is field is static for the sake of the closeOpenRecentCasesWindow * This is field is static for the sake of the closeOpenRecentCasesWindow
* method. * method.
*/ */
private static JDialog recentCasesWindow; private static JDialog recentCasesWindow;
private static JDialog autoIngestCasePanelWindow;
public static void closeOpenRecentCasesWindow() { public static void closeOpenRecentCasesWindow() {
if (null != recentCasesWindow) { if (null != recentCasesWindow) {
@ -56,15 +50,9 @@ public class CueBannerPanel extends javax.swing.JPanel {
} }
} }
public static void closeAutoIngestCasesWindow() {
if (null != autoIngestCasePanelWindow) {
autoIngestCasePanelWindow.setVisible(false);
}
}
public CueBannerPanel() { public CueBannerPanel() {
initComponents(); initComponents();
customizeComponents(); initRecentCasesWindow();
enableComponents(); enableComponents();
} }
@ -75,7 +63,7 @@ public class CueBannerPanel extends javax.swing.JPanel {
ImageIcon icon = new ImageIcon(cl.getResource(welcomeLogo)); ImageIcon icon = new ImageIcon(cl.getResource(welcomeLogo));
autopsyLogo.setIcon(icon); autopsyLogo.setIcon(icon);
} }
customizeComponents(); initRecentCasesWindow();
enableComponents(); enableComponents();
} }
@ -91,11 +79,6 @@ public class CueBannerPanel extends javax.swing.JPanel {
enableComponents(); enableComponents();
} }
private void customizeComponents() {
initRecentCasesWindow();
initAutoIngestCasesWindow();
}
private void initRecentCasesWindow() { private void initRecentCasesWindow() {
recentCasesWindow = new JDialog( recentCasesWindow = new JDialog(
WindowManager.getDefault().getMainWindow(), WindowManager.getDefault().getMainWindow(),
@ -119,38 +102,14 @@ public class CueBannerPanel extends javax.swing.JPanel {
recentCasesWindow.setResizable(false); recentCasesWindow.setResizable(false);
} }
private void initAutoIngestCasesWindow() {
autoIngestCasePanelWindow = new JDialog(
WindowManager.getDefault().getMainWindow(),
REVIEW_MODE_TITLE,
Dialog.ModalityType.APPLICATION_MODAL);
autoIngestCasePanelWindow.getRootPane().registerKeyboardAction(
e -> {
autoIngestCasePanelWindow.setVisible(false);
},
KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);
OpenRecentCasePanel recentCasesPanel = OpenRecentCasePanel.getInstance();
recentCasesPanel.setCloseButtonActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
autoIngestCasePanelWindow.setVisible(false);
}
});
AutoIngestCasePanelInterface autoIngestCasePanel = Lookup.getDefault().lookup(AutoIngestCasePanelInterface.class);
autoIngestCasePanel.addWindowStateListener(autoIngestCasePanelWindow);
autoIngestCasePanelWindow.add((JPanel)autoIngestCasePanel);
autoIngestCasePanelWindow.pack();
autoIngestCasePanelWindow.setResizable(false);
}
private void enableComponents() { private void enableComponents() {
boolean enableOpenRecentCaseButton = (RecentCases.getInstance().getTotalRecentCases() > 0); boolean enableOpenRecentCaseButton = (RecentCases.getInstance().getTotalRecentCases() > 0);
openRecentCaseButton.setEnabled(enableOpenRecentCaseButton); openRecentCaseButton.setEnabled(enableOpenRecentCaseButton);
openRecentCaseLabel.setEnabled(enableOpenRecentCaseButton); openRecentCaseLabel.setEnabled(enableOpenRecentCaseButton);
boolean showOpenAutoIngestCaseButton = (UserPreferences.getMode() == UserPreferences.SelectedMode.REVIEW); boolean enableOpenMultiUserCaseButton = UserPreferences.getIsMultiUserModeEnabled();
openAutoIngestCaseButton.setVisible(showOpenAutoIngestCaseButton); openMultiUserCaseButton.setEnabled(enableOpenMultiUserCaseButton);
openAutoIngestCaseLabel.setVisible(showOpenAutoIngestCaseButton); openMultiUserCaseLabel.setEnabled(enableOpenMultiUserCaseButton);
} }
/** /**
@ -172,8 +131,8 @@ public class CueBannerPanel extends javax.swing.JPanel {
openExistingCaseLabel = new javax.swing.JLabel(); openExistingCaseLabel = new javax.swing.JLabel();
closeButton = new javax.swing.JButton(); closeButton = new javax.swing.JButton();
jSeparator1 = new javax.swing.JSeparator(); jSeparator1 = new javax.swing.JSeparator();
openAutoIngestCaseButton = new javax.swing.JButton(); openMultiUserCaseButton = new javax.swing.JButton();
openAutoIngestCaseLabel = new javax.swing.JLabel(); openMultiUserCaseLabel = new javax.swing.JLabel();
autopsyLogo.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/casemodule/welcome_logo.png"))); // NOI18N autopsyLogo.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/casemodule/welcome_logo.png"))); // NOI18N
autopsyLogo.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.autopsyLogo.text")); // NOI18N autopsyLogo.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.autopsyLogo.text")); // NOI18N
@ -229,21 +188,21 @@ public class CueBannerPanel extends javax.swing.JPanel {
jSeparator1.setOrientation(javax.swing.SwingConstants.VERTICAL); jSeparator1.setOrientation(javax.swing.SwingConstants.VERTICAL);
openAutoIngestCaseButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/casemodule/btn_icon_open_existing.png"))); // NOI18N openMultiUserCaseButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/casemodule/btn_icon_open_existing.png"))); // NOI18N
openAutoIngestCaseButton.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.openAutoIngestCaseButton.text")); // NOI18N openMultiUserCaseButton.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.openMultiUserCaseButton.text")); // NOI18N
openAutoIngestCaseButton.setBorder(null); openMultiUserCaseButton.setBorder(null);
openAutoIngestCaseButton.setBorderPainted(false); openMultiUserCaseButton.setBorderPainted(false);
openAutoIngestCaseButton.setContentAreaFilled(false); openMultiUserCaseButton.setContentAreaFilled(false);
openAutoIngestCaseButton.setMargin(new java.awt.Insets(1, 1, 1, 1)); openMultiUserCaseButton.setMargin(new java.awt.Insets(1, 1, 1, 1));
openAutoIngestCaseButton.setPreferredSize(new java.awt.Dimension(64, 64)); openMultiUserCaseButton.setPreferredSize(new java.awt.Dimension(64, 64));
openAutoIngestCaseButton.addActionListener(new java.awt.event.ActionListener() { openMultiUserCaseButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
openAutoIngestCaseButtonActionPerformed(evt); openMultiUserCaseButtonActionPerformed(evt);
} }
}); });
openAutoIngestCaseLabel.setFont(openAutoIngestCaseLabel.getFont().deriveFont(openAutoIngestCaseLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 13)); openMultiUserCaseLabel.setFont(openMultiUserCaseLabel.getFont().deriveFont(openMultiUserCaseLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 13));
openAutoIngestCaseLabel.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.openAutoIngestCaseLabel.text")); // NOI18N openMultiUserCaseLabel.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.openMultiUserCaseLabel.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
@ -261,13 +220,13 @@ public class CueBannerPanel extends javax.swing.JPanel {
.addComponent(createNewCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(createNewCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(openRecentCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(openRecentCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(openExistingCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(openExistingCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(openAutoIngestCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(openMultiUserCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(createNewCaseLabel) .addComponent(createNewCaseLabel)
.addComponent(openRecentCaseLabel) .addComponent(openRecentCaseLabel)
.addComponent(openExistingCaseLabel) .addComponent(openExistingCaseLabel)
.addComponent(openAutoIngestCaseLabel))) .addComponent(openMultiUserCaseLabel)))
.addComponent(closeButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 73, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(closeButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 73, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap()) .addContainerGap())
); );
@ -290,9 +249,9 @@ public class CueBannerPanel extends javax.swing.JPanel {
.addComponent(openExistingCaseLabel)) .addComponent(openExistingCaseLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(openAutoIngestCaseButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 58, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(openMultiUserCaseButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 58, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(openAutoIngestCaseLabel) .addComponent(openMultiUserCaseLabel)
.addGap(20, 20, 20)))) .addGap(20, 20, 20))))
.addComponent(jSeparator1) .addComponent(jSeparator1)
.addComponent(autopsyLogo, javax.swing.GroupLayout.PREFERRED_SIZE, 257, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(autopsyLogo, javax.swing.GroupLayout.PREFERRED_SIZE, 257, javax.swing.GroupLayout.PREFERRED_SIZE))
@ -316,10 +275,11 @@ public class CueBannerPanel extends javax.swing.JPanel {
recentCasesWindow.setVisible(true); recentCasesWindow.setVisible(true);
}//GEN-LAST:event_openRecentCaseButtonActionPerformed }//GEN-LAST:event_openRecentCaseButtonActionPerformed
private void openAutoIngestCaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openAutoIngestCaseButtonActionPerformed private void openMultiUserCaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openMultiUserCaseButtonActionPerformed
autoIngestCasePanelWindow.setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); MultiUserCasesDialog multiUserCaseWindow = MultiUserCasesDialog.getInstance();
autoIngestCasePanelWindow.setVisible(true); multiUserCaseWindow.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
}//GEN-LAST:event_openAutoIngestCaseButtonActionPerformed multiUserCaseWindow.setVisible(true);
}//GEN-LAST:event_openMultiUserCaseButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel autopsyLogo; private javax.swing.JLabel autopsyLogo;
@ -327,8 +287,8 @@ public class CueBannerPanel extends javax.swing.JPanel {
private javax.swing.JButton createNewCaseButton; private javax.swing.JButton createNewCaseButton;
private javax.swing.JLabel createNewCaseLabel; private javax.swing.JLabel createNewCaseLabel;
private javax.swing.JSeparator jSeparator1; private javax.swing.JSeparator jSeparator1;
private javax.swing.JButton openAutoIngestCaseButton; private javax.swing.JButton openMultiUserCaseButton;
private javax.swing.JLabel openAutoIngestCaseLabel; private javax.swing.JLabel openMultiUserCaseLabel;
private javax.swing.JButton openExistingCaseButton; private javax.swing.JButton openExistingCaseButton;
private javax.swing.JLabel openExistingCaseLabel; private javax.swing.JLabel openExistingCaseLabel;
private javax.swing.JButton openRecentCaseButton; private javax.swing.JButton openRecentCaseButton;

View File

@ -0,0 +1,442 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 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.casemodule;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coordinationservice.CaseNodeData;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* Handles locating and opening multi-user cases.
*/
final class MultiUserCaseManager {
private static final Logger LOGGER = Logger.getLogger(MultiUserCaseManager.class.getName());
private static final String ALERT_FILE_NAME = "autoingest.alert";
private static MultiUserCaseManager instance;
private CoordinationService coordinationService;
/**
* Gets the multi-user case manager.
*
* @return The multi-user case manager singleton.
*
* @throws MultiUserCaseManagerException
*/
synchronized static MultiUserCaseManager getInstance() throws MultiUserCaseManager.MultiUserCaseManagerException {
if (null == instance) {
instance = new MultiUserCaseManager();
}
return instance;
}
/**
* Constructs an object that handles locating and opening multi-user cases.
*
* @throws MultiUserCaseManagerException
*/
private MultiUserCaseManager() throws MultiUserCaseManagerException {
try {
coordinationService = CoordinationService.getInstance();
} catch (CoordinationServiceException ex) {
throw new MultiUserCaseManager.MultiUserCaseManagerException("Failed to get the coordination service.", ex);
}
}
/**
* Gets a list of the cases in the top level case folder
*
* @return List of cases.
*
* @throws CoordinationServiceException
*/
List<MultiUserCase> getCases() throws CoordinationServiceException {
List<MultiUserCase> cases = new ArrayList<>();
List<String> nodeList = coordinationService.getNodeList(CoordinationService.CategoryNode.CASES);
for (String node : nodeList) {
Path casePath = Paths.get(node);
File caseFolder = casePath.toFile();
if (caseFolder.exists()) {
/*
* Search for '*.aut' and 'autoingest.alert' files.
*/
File[] fileArray = caseFolder.listFiles();
if (fileArray == null) {
continue;
}
String autFilePath = null;
boolean alertFileFound = false;
for (File file : fileArray) {
String name = file.getName().toLowerCase();
if (autFilePath == null && name.endsWith(".aut")) {
autFilePath = file.getAbsolutePath();
if (!alertFileFound) {
continue;
}
}
if (!alertFileFound && name.endsWith(ALERT_FILE_NAME)) {
alertFileFound = true;
}
if (autFilePath != null && alertFileFound) {
break;
}
}
if (autFilePath != null) {
try {
CaseStatus caseStatus;
if (alertFileFound) {
/*
* When an alert file exists, ignore the node data
* and use the ALERT status.
*/
caseStatus = CaseStatus.ALERT;
} else {
byte[] rawData = coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, node);
if (rawData != null && rawData.length > 0) {
/*
* When node data exists, use the status stored
* in the node data.
*/
CaseNodeData caseNodeData = new CaseNodeData(rawData);
if (caseNodeData.getErrorsOccurred()) {
caseStatus = CaseStatus.ALERT;
} else {
caseStatus = CaseStatus.OK;
}
} else {
/*
* When no node data is available, use the 'OK'
* status to avoid confusing the end-user.
*/
caseStatus = CaseStatus.OK;
}
}
CaseMetadata caseMetadata = new CaseMetadata(Paths.get(autFilePath));
cases.add(new MultiUserCase(casePath, caseMetadata, caseStatus));
} catch (CaseMetadata.CaseMetadataException | MultiUserCase.MultiUserCaseException ex) {
LOGGER.log(Level.SEVERE, String.format("Error reading case metadata file '%s'.", autFilePath), ex);
} catch (InterruptedException | CaseNodeData.InvalidDataException ex) {
LOGGER.log(Level.SEVERE, String.format("Error reading case node data for '%s'.", node), ex);
}
}
}
}
return cases;
}
/**
* Opens a multi-user case.
*
* @param caseMetadataFilePath Path to the case metadata file.
*
* @throws CaseActionException
*/
synchronized void openCase(Path caseMetadataFilePath) throws CaseActionException {
/*
* Open the case.
*/
Case.openAsCurrentCase(caseMetadataFilePath.toString());
}
/**
* Exception type thrown when there is an error completing a multi-user case
* manager operation.
*/
static final class MultiUserCaseManagerException extends Exception {
private static final long serialVersionUID = 1L;
/**
* Constructs an instance of the exception type thrown when there is an
* error completing a multi-user case manager operation.
*
* @param message The exception message.
*/
private MultiUserCaseManagerException(String message) {
super(message);
}
/**
* Constructs an instance of the exception type thrown when there is an
* error completing a multi-user case manager operation.
*
* @param message The exception message.
* @param cause A Throwable cause for the error.
*/
private MultiUserCaseManagerException(String message, Throwable cause) {
super(message, cause);
}
}
/**
* A representation of a multi-user case.
*/
static class MultiUserCase implements Comparable<MultiUserCase> {
private final Path caseDirectoryPath;
private final String caseDisplayName;
private final String metadataFileName;
private final Date createDate;
private final Date lastAccessedDate;
private CaseStatus status;
/**
* Constructs a representation of a multi-user case
*
* @param caseDirectoryPath The case directory path.
* @param caseMetadata The case metadata.
*
* @throws MultiUserCaseException If no case metadata (.aut) file is
* found in the case directory.
*/
MultiUserCase(Path caseDirectoryPath, CaseMetadata caseMetadata, CaseStatus status) throws MultiUserCaseException {
this.caseDirectoryPath = caseDirectoryPath;
caseDisplayName = caseMetadata.getCaseDisplayName();
metadataFileName = caseMetadata.getFilePath().getFileName().toString();
this.status = status;
BasicFileAttributes fileAttrs = null;
try {
fileAttrs = Files.readAttributes(Paths.get(caseDirectoryPath.toString(), metadataFileName), BasicFileAttributes.class);
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, String.format("Error reading file attributes of case metadata file in %s, will use current time for case createDate/lastModfiedDate", caseDirectoryPath), ex);
}
if (null != fileAttrs) {
createDate = new Date(fileAttrs.creationTime().toMillis());
lastAccessedDate = new Date(fileAttrs.lastAccessTime().toMillis());
} else {
createDate = new Date();
lastAccessedDate = new Date();
}
}
/**
* Gets the case directory path.
*
* @return The case directory path.
*/
Path getCaseDirectoryPath() {
return this.caseDirectoryPath;
}
/**
* Gets the case display name. This may differ from the name supplied to
* the directory or metadata file names if a case has been renamed.
*
* @return The case display name.
*/
String getCaseDisplayName() {
return this.caseDisplayName;
}
/**
* Gets the creation date for the case, defined as the create time of
* the case metadata file.
*
* @return The case creation date.
*/
Date getCreationDate() {
return this.createDate;
}
/**
* Gets the last accessed date for the case, defined as the last
* accessed time of the case metadata file.
*
* @return The last accessed date.
*/
Date getLastAccessedDate() {
return this.lastAccessedDate;
}
/**
* Gets metadata (.aut) file name.
*
* @return The metadata file name.
*/
String getMetadataFileName() {
return this.metadataFileName;
}
/**
* Gets the status of this case.
*
* @return See CaseStatus enum definition.
*/
CaseStatus getStatus() {
return status;
}
/**
* Gets the case metadata from a case directory path.
*
* @param caseDirectoryPath The case directory path.
*
* @return Case metadata.
*
* @throws CaseMetadata.CaseMetadataException If the CaseMetadata object
* cannot be constructed.
* @throws MultiUserCaseException If no case metadata (.aut)
* file is found in the case
* directory.
*/
private CaseMetadata getCaseMetadataFromCaseDirectoryPath(Path caseDirectoryPath) throws CaseMetadata.CaseMetadataException, MultiUserCaseException {
CaseMetadata caseMetadata = null;
File directory = new File(caseDirectoryPath.toString());
if (directory.isDirectory()) {
File autFile = null;
/*
* Attempt to find an AUT file via a directory scan.
*/
for (File file : directory.listFiles()) {
if (file.getName().toLowerCase().endsWith(CaseMetadata.getFileExtension()) && file.isFile()) {
autFile = file;
break;
}
}
if (autFile == null || !autFile.isFile()) {
throw new MultiUserCaseException(String.format("No case metadata (.aut) file found in the case directory '%s'.", caseDirectoryPath.toString()));
}
caseMetadata = new CaseMetadata(Paths.get(autFile.getAbsolutePath()));
}
return caseMetadata;
}
/**
* Indicates whether or not some other object is "equal to" this
* MultiUserCase object.
*
* @param other The other object.
*
* @return True or false.
*/
@Override
public boolean equals(Object other) {
if (!(other instanceof MultiUserCase)) {
return false;
}
if (other == this) {
return true;
}
return this.caseDirectoryPath.toString().equals(((MultiUserCase) other).caseDirectoryPath.toString());
}
/**
* Returns a hash code value for this MultiUserCase object.
*
* @return The has code.
*/
@Override
public int hashCode() {
int hash = 7;
hash = 71 * hash + Objects.hashCode(this.caseDirectoryPath);
hash = 71 * hash + Objects.hashCode(this.createDate);
hash = 71 * hash + Objects.hashCode(this.caseDisplayName);
return hash;
}
/**
* Compares this MultiUserCase object with another MultiUserCase object
* for order.
*/
@Override
public int compareTo(MultiUserCase other) {
return -this.lastAccessedDate.compareTo(other.getLastAccessedDate());
}
/**
* Comparator for a descending order sort on date created.
*/
static class LastAccessedDateDescendingComparator implements Comparator<MultiUserCase> {
/**
* Compares two MultiUserCase objects for order based on last
* accessed date (descending).
*
* @param object The first MultiUserCase object
* @param otherObject The second MultiUserCase object.
*
* @return A negative integer, zero, or a positive integer as the
* first argument is less than, equal to, or greater than
* the second.
*/
@Override
public int compare(MultiUserCase object, MultiUserCase otherObject) {
return -object.getLastAccessedDate().compareTo(otherObject.getLastAccessedDate());
}
}
/**
* Exception thrown when there is a problem creating a multi-user case.
*/
final class MultiUserCaseException extends Exception {
private static final long serialVersionUID = 1L;
/**
* Constructs an exception to throw when there is a problem creating
* a multi-user case.
*
* @param message The exception message.
*/
private MultiUserCaseException(String message) {
super(message);
}
/**
* Constructs an exception to throw when there is a problem creating
* a multi-user case.
*
* @param message The exception message.
* @param cause The cause of the exception, if it was an
* exception.
*/
private MultiUserCaseException(String message, Throwable cause) {
super(message, cause);
}
}
}
static enum CaseStatus {
OK,
ALERT
}
}

View File

@ -0,0 +1,89 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 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.casemodule;
import java.awt.Dialog;
import java.awt.event.KeyEvent;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.KeyStroke;
import org.openide.windows.WindowManager;
/**
* This class extends a JDialog and maintains the MultiUserCasesPanel.
*/
final class MultiUserCasesDialog extends JDialog {
private static final long serialVersionUID = 1L;
private static final String REVIEW_MODE_TITLE = "Open Multi-User Case";
private static MultiUserCasesPanel multiUserCasesPanel;
private static MultiUserCasesDialog instance;
/**
* Gets the instance of the MultiuserCasesDialog.
*
* @return The instance.
*/
static public MultiUserCasesDialog getInstance() {
if(instance == null) {
instance = new MultiUserCasesDialog();
instance.init();
}
return instance;
}
/**
* Constructs a MultiUserCasesDialog object.
*/
private MultiUserCasesDialog() {
super(WindowManager.getDefault().getMainWindow(),
REVIEW_MODE_TITLE,
Dialog.ModalityType.APPLICATION_MODAL);
}
/**
* Initializes the multi-user cases panel.
*/
private void init() {
getRootPane().registerKeyboardAction(
e -> {
setVisible(false);
},
KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);
multiUserCasesPanel = new MultiUserCasesPanel(this);
add(multiUserCasesPanel);
pack();
setResizable(false);
}
/**
* Set the dialog visibility. When setting it to visible, the contents will
* refresh.
*
* @param value True or false.
*/
@Override
public void setVisible(boolean value) {
if(value) {
multiUserCasesPanel.refresh();
}
super.setVisible(value);
}
}

View File

@ -45,7 +45,7 @@
<Component id="bnRefresh" min="-2" max="-2" attributes="0"/> <Component id="bnRefresh" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="4" max="-2" attributes="0"/> <EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
</Group> </Group>
<Component id="scrollPaneTable" pref="1007" max="32767" attributes="0"/> <Component id="scrollPaneTable" max="32767" attributes="0"/>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
</Group> </Group>
@ -82,7 +82,7 @@
<Component class="javax.swing.JButton" name="bnOpen"> <Component class="javax.swing.JButton" name="bnOpen">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.bnOpen.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="MultiUserCasesPanel.bnOpen.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="enabled" type="boolean" value="false"/> <Property name="enabled" type="boolean" value="false"/>
</Properties> </Properties>
@ -99,11 +99,9 @@
<SubComponents> <SubComponents>
<Component class="javax.swing.JTable" name="casesTable"> <Component class="javax.swing.JTable" name="casesTable">
<Properties> <Properties>
<Property name="autoCreateRowSorter" type="boolean" value="true"/>
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="caseTableModel" type="code"/> <Connection code="caseTableModel" type="code"/>
</Property> </Property>
<Property name="autoResizeMode" type="int" value="4"/>
<Property name="rowHeight" type="int" value="20"/> <Property name="rowHeight" type="int" value="20"/>
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor"> <Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
<JTableSelectionModel selectionMode="0"/> <JTableSelectionModel selectionMode="0"/>
@ -118,7 +116,7 @@
<Component class="javax.swing.JButton" name="bnRefresh"> <Component class="javax.swing.JButton" name="bnRefresh">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.bnRefresh.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="MultiUserCasesPanel.bnRefresh.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events> <Events>
@ -153,7 +151,7 @@
</Property> </Property>
<Property name="selected" type="boolean" value="true"/> <Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.rbAllCases.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="MultiUserCasesPanel.rbAllCases.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events> <Events>
@ -165,10 +163,10 @@
<Component class="javax.swing.JButton" name="bnShowLog"> <Component class="javax.swing.JButton" name="bnShowLog">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.bnShowLog.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="MultiUserCasesPanel.bnShowLog.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.bnShowLog.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="MultiUserCasesPanel.bnShowLog.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="enabled" type="boolean" value="false"/> <Property name="enabled" type="boolean" value="false"/>
</Properties> </Properties>
@ -182,7 +180,7 @@
<ComponentRef name="rbGroupHistoryLength"/> <ComponentRef name="rbGroupHistoryLength"/>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.rbDays.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="MultiUserCasesPanel.rbDays.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="name" type="java.lang.String" value="" noResource="true"/> <Property name="name" type="java.lang.String" value="" noResource="true"/>
</Properties> </Properties>
@ -196,7 +194,7 @@
<ComponentRef name="rbGroupHistoryLength"/> <ComponentRef name="rbGroupHistoryLength"/>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.rbWeeks.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="MultiUserCasesPanel.rbWeeks.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events> <Events>
@ -209,7 +207,7 @@
<ComponentRef name="rbGroupHistoryLength"/> <ComponentRef name="rbGroupHistoryLength"/>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.rbMonths.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="MultiUserCasesPanel.rbMonths.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events> <Events>
@ -222,7 +220,7 @@
<Font name="Tahoma" size="12" style="0"/> <Font name="Tahoma" size="12" style="0"/>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.rbGroupLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="MultiUserCasesPanel.rbGroupLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
</Component> </Component>

View File

@ -16,52 +16,42 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.experimental.autoingest; package org.sleuthkit.autopsy.casemodule;
import java.awt.Cursor; import java.awt.Cursor;
import java.awt.Desktop; import java.awt.Desktop;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.JDialog; import javax.swing.JDialog;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.JPanel; import javax.swing.RowSorter;
import javax.swing.SwingWorker; import javax.swing.SortOrder;
import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionEvent;
import javax.swing.table.DefaultTableModel; import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn; import javax.swing.table.TableColumn;
import org.openide.util.NbBundle; import javax.swing.table.TableRowSorter;
import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.casemodule.MultiUserCaseManager.MultiUserCase;
import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.casemodule.CaseActionCancelledException;
import org.sleuthkit.autopsy.casemodule.CaseMetadata;
import org.sleuthkit.autopsy.casemodule.StartupWindowProvider;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.guiutils.LongDateCellRenderer;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.casemodule.AutoIngestCasePanelInterface; import org.sleuthkit.autopsy.guiutils.GrayableCellRenderer;
import org.sleuthkit.autopsy.casemodule.CueBannerPanel; import org.sleuthkit.autopsy.guiutils.StatusIconCellRenderer;
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import org.sleuthkit.autopsy.experimental.configuration.StartupWindow;
/** /**
* A panel that allows a user to open cases created by auto ingest. * A panel that allows a user to open cases created by auto ingest.
*/ */
@ServiceProvider(service = AutoIngestCasePanelInterface.class) final class MultiUserCasesPanel extends javax.swing.JPanel {
public final class AutoIngestCasePanel extends JPanel implements AutoIngestCasePanelInterface {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(AutoIngestCasePanel.class.getName()); private static final Logger LOGGER = Logger.getLogger(MultiUserCasesPanel.class.getName());
private static final AutoIngestCase.LastAccessedDateDescendingComparator reverseDateModifiedComparator = new AutoIngestCase.LastAccessedDateDescendingComparator(); private static final String LOG_FILE_NAME = "auto_ingest_log.txt";
private static final MultiUserCaseManager.MultiUserCase.LastAccessedDateDescendingComparator REVERSE_DATE_MODIFIED_COMPARATOR = new MultiUserCaseManager.MultiUserCase.LastAccessedDateDescendingComparator();
private static final int CASE_COL_MIN_WIDTH = 30; private static final int CASE_COL_MIN_WIDTH = 30;
private static final int CASE_COL_MAX_WIDTH = 2000; private static final int CASE_COL_MAX_WIDTH = 2000;
private static final int CASE_COL_PREFERRED_WIDTH = 300; private static final int CASE_COL_PREFERRED_WIDTH = 300;
@ -71,9 +61,6 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
private static final int STATUS_COL_MIN_WIDTH = 55; private static final int STATUS_COL_MIN_WIDTH = 55;
private static final int STATUS_COL_MAX_WIDTH = 250; private static final int STATUS_COL_MAX_WIDTH = 250;
private static final int STATUS_COL_PREFERRED_WIDTH = 60; private static final int STATUS_COL_PREFERRED_WIDTH = 60;
private static final int MILLIS_TO_WAIT_BEFORE_STARTING = 500;
private static final int MILLIS_TO_WAIT_BETWEEN_UPDATES = 300000;
private ScheduledThreadPoolExecutor casesTableRefreshExecutor;
/* /*
* The JTable table model for the cases table presented by this view is * The JTable table model for the cases table presented by this view is
@ -82,11 +69,12 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
* TODO (RC): Consider unifying this stuff in an enum as in * TODO (RC): Consider unifying this stuff in an enum as in
* AutoIngestDashboard to make it less error prone. * AutoIngestDashboard to make it less error prone.
*/ */
private static final String CASE_HEADER = org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.CaseHeaderText"); private static final String CASE_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.CaseHeaderText");
private static final String CREATEDTIME_HEADER = org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.CreatedTimeHeaderText"); private static final String CREATEDTIME_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.CreatedTimeHeaderText");
private static final String COMPLETEDTIME_HEADER = org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.LastAccessedTimeHeaderText"); private static final String COMPLETEDTIME_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.LastAccessedTimeHeaderText");
private static final String STATUS_ICON_HEADER = org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.StatusIconHeaderText"); private static final String STATUS_ICON_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.StatusIconHeaderText");
private static final String OUTPUT_FOLDER_HEADER = org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.OutputFolderHeaderText"); private static final String OUTPUT_FOLDER_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.OutputFolderHeaderText");
private static final String METADATA_FILE_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.MetadataFileHeaderText");
enum COLUMN_HEADERS { enum COLUMN_HEADERS {
@ -94,51 +82,20 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
CREATEDTIME, CREATEDTIME,
COMPLETEDTIME, COMPLETEDTIME,
STATUS_ICON, STATUS_ICON,
OUTPUTFOLDER OUTPUTFOLDER,
METADATA_FILE
} }
private final String[] columnNames = {CASE_HEADER, CREATEDTIME_HEADER, COMPLETEDTIME_HEADER, STATUS_ICON_HEADER, OUTPUT_FOLDER_HEADER}; private final String[] columnNames = {CASE_HEADER, CREATEDTIME_HEADER, COMPLETEDTIME_HEADER, STATUS_ICON_HEADER, OUTPUT_FOLDER_HEADER, METADATA_FILE_HEADER};
private DefaultTableModel caseTableModel; private DefaultTableModel caseTableModel;
private Path currentlySelectedCase = null; private Path currentlySelectedCase = null;
private JDialog parentDialog;
public AutoIngestCasePanel() {
init(null);
}
@Override
public void addWindowStateListener(JDialog parent) {
/*
* Add a window state listener that starts and stops refreshing of the
* cases table.
*/
parent.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
stopCasesTableRefreshes();
}
@Override
public void windowActivated(WindowEvent e) {
startCasesTableRefreshes();
}
@Override
public void windowClosed(WindowEvent e) {
stopCasesTableRefreshes();
}
});
}
/** /**
* Constructs a panel that allows a user to open cases created by automated * Constructs a panel that allows a user to open cases created by automated
* ingest. * ingest.
*
* @param parent The parent dialog for this panel.
*/ */
public AutoIngestCasePanel(JDialog parent) { MultiUserCasesPanel(JDialog parentDialog) {
init(parent); this.parentDialog = parentDialog;
}
public void init(JDialog parent) {
caseTableModel = new DefaultTableModel(columnNames, 0) { caseTableModel = new DefaultTableModel(columnNames, 0) {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -146,6 +103,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
public boolean isCellEditable(int row, int column) { public boolean isCellEditable(int row, int column) {
return false; return false;
} }
@Override @Override
public Class<?> getColumnClass(int col) { public Class<?> getColumnClass(int col) {
if (this.getColumnName(col).equals(CREATEDTIME_HEADER) || this.getColumnName(col).equals(COMPLETEDTIME_HEADER)) { if (this.getColumnName(col).equals(CREATEDTIME_HEADER) || this.getColumnName(col).equals(COMPLETEDTIME_HEADER)) {
@ -184,13 +142,15 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
theColumn.setWidth(TIME_COL_PREFERRED_WIDTH); theColumn.setWidth(TIME_COL_PREFERRED_WIDTH);
theColumn = casesTable.getColumn(STATUS_ICON_HEADER); theColumn = casesTable.getColumn(STATUS_ICON_HEADER);
theColumn.setCellRenderer(new CaseStatusIconCellRenderer()); theColumn.setCellRenderer(new StatusIconCellRenderer());
theColumn.setMinWidth(STATUS_COL_MIN_WIDTH); theColumn.setMinWidth(STATUS_COL_MIN_WIDTH);
theColumn.setMaxWidth(STATUS_COL_MAX_WIDTH); theColumn.setMaxWidth(STATUS_COL_MAX_WIDTH);
theColumn.setPreferredWidth(STATUS_COL_PREFERRED_WIDTH); theColumn.setPreferredWidth(STATUS_COL_PREFERRED_WIDTH);
theColumn.setWidth(STATUS_COL_PREFERRED_WIDTH); theColumn.setWidth(STATUS_COL_PREFERRED_WIDTH);
casesTable.removeColumn(casesTable.getColumn(OUTPUT_FOLDER_HEADER)); casesTable.removeColumn(casesTable.getColumn(OUTPUT_FOLDER_HEADER));
casesTable.removeColumn(casesTable.getColumn(METADATA_FILE_HEADER));
casesTable.setRowSorter(new RowSorter<>(caseTableModel));
/* /*
* Listen for row selection changes and set button state for the current * Listen for row selection changes and set button state for the current
@ -203,75 +163,39 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
} }
setButtons(); setButtons();
}); });
/*
* Add a window state listener that starts and stops refreshing of the
* cases table.
*/
if (parent != null) {
parent.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
stopCasesTableRefreshes();
}
@Override
public void windowActivated(WindowEvent e) {
startCasesTableRefreshes();
}
@Override
public void windowClosed(WindowEvent e) {
stopCasesTableRefreshes();
}
});
}
}
/**
* Start doing periodic refreshes of the cases table.
*/
private void startCasesTableRefreshes() {
if (null == casesTableRefreshExecutor) {
casesTableRefreshExecutor = new ScheduledThreadPoolExecutor(1);
this.casesTableRefreshExecutor.scheduleAtFixedRate(() -> {
refreshCasesTable();
}, MILLIS_TO_WAIT_BEFORE_STARTING, MILLIS_TO_WAIT_BETWEEN_UPDATES, TimeUnit.MILLISECONDS);
}
}
/**
* Stop doing periodic refreshes of the cases table.
*/
private void stopCasesTableRefreshes() {
if (null != casesTableRefreshExecutor) {
casesTableRefreshExecutor.shutdown();
}
this.casesTableRefreshExecutor = null;
}
/*
* Updates the view presented by the panel.
*/
public void updateView() {
Thread thread = new Thread(() -> {
refreshCasesTable();
});
thread.start();
} }
/** /**
* Gets the list of cases known to the review mode cases manager and * Gets the list of cases known to the review mode cases manager and
* refreshes the cases table. * refreshes the cases table.
*/ */
private void refreshCasesTable() { void refresh() {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try { try {
currentlySelectedCase = getSelectedCase(); currentlySelectedCase = getSelectedCase();
AutoIngestCaseManager manager = AutoIngestCaseManager.getInstance(); MultiUserCaseManager manager = MultiUserCaseManager.getInstance();
List<AutoIngestCase> theModel = manager.getCases(); List<MultiUserCase> cases = manager.getCases();
EventQueue.invokeLater(new CaseTableRefreshTask(theModel)); cases.sort(REVERSE_DATE_MODIFIED_COMPARATOR);
} catch (Exception ex) { caseTableModel.setRowCount(0);
logger.log(Level.SEVERE, "Unexpected exception in refreshCasesTable", ex); //NON-NLS long now = new Date().getTime();
for (MultiUserCase autoIngestCase : cases) {
if (passesTimeFilter(now, autoIngestCase.getLastAccessedDate().getTime())) {
caseTableModel.addRow(new Object[]{
autoIngestCase.getCaseDisplayName(),
autoIngestCase.getCreationDate(),
autoIngestCase.getLastAccessedDate(),
(MultiUserCaseManager.CaseStatus.OK != autoIngestCase.getStatus()) ? StatusIconCellRenderer.Status.WARNING : StatusIconCellRenderer.Status.OK,
autoIngestCase.getCaseDirectoryPath().toString(),
autoIngestCase.getMetadataFileName()});
}
}
setSelectedCase(currentlySelectedCase);
setButtons();
} catch (MultiUserCaseManager.MultiUserCaseManagerException | CoordinationService.CoordinationServiceException ex) {
LOGGER.log(Level.SEVERE, "Unexpected exception while refreshing the table.", ex); //NON-NLS
} finally {
setCursor(null);
} }
} }
@ -320,103 +244,108 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
* in the cases table. * in the cases table.
*/ */
private void setButtons() { private void setButtons() {
boolean enabled = casesTable.getSelectedRow() >= 0 && casesTable.getSelectedRow() < casesTable.getRowCount(); boolean openEnabled = casesTable.getSelectedRow() >= 0 && casesTable.getSelectedRow() < casesTable.getRowCount();
bnOpen.setEnabled(enabled); bnOpen.setEnabled(openEnabled);
bnShowLog.setEnabled(enabled);
Path pathToLog = getSelectedCaseLogFilePath();
boolean showLogEnabled = openEnabled && pathToLog != null && pathToLog.toFile().exists();
bnShowLog.setEnabled(showLogEnabled);
} }
/** /**
* Opens a case. * Retrieves the log file path for the selected case in the cases table.
*
* @return The case log path.
*/
private Path getSelectedCaseLogFilePath() {
Path retValue = null;
int selectedRow = casesTable.getSelectedRow();
int rowCount = casesTable.getRowCount();
if (selectedRow >= 0 && selectedRow < rowCount) {
String caseDirectory = (String) caseTableModel.getValueAt(casesTable.convertRowIndexToModel(selectedRow), COLUMN_HEADERS.OUTPUTFOLDER.ordinal());
retValue = Paths.get(caseDirectory, LOG_FILE_NAME);
}
return retValue;
}
/**
* Open a case.
* *
* @param caseMetadataFilePath The path to the case metadata file. * @param caseMetadataFilePath The path to the case metadata file.
*/ */
private void openCase(Path caseMetadataFilePath) { private void openCase(Path caseMetadataFilePath) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
new SwingWorker<Void, Void>() { try {
StartupWindowProvider.getInstance().close();
@Override if (parentDialog != null) {
protected Void doInBackground() throws Exception { parentDialog.setVisible(false);
AutoIngestCaseManager.getInstance().openCase(caseMetadataFilePath);
stopCasesTableRefreshes();
StartupWindowProvider.getInstance().close();
CueBannerPanel.closeAutoIngestCasesWindow();
return null;
} }
MultiUserCaseManager.getInstance().openCase(caseMetadataFilePath);
@Override } catch (CaseActionException | MultiUserCaseManager.MultiUserCaseManagerException ex) {
protected void done() { if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) {
try { LOGGER.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS
get(); MessageNotifyUtil.Message.error(ex.getCause().getLocalizedMessage());
} catch (InterruptedException | ExecutionException ex) {
if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) {
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS
MessageNotifyUtil.Message.error(ex.getCause().getLocalizedMessage());
}
StartupWindowProvider.getInstance().open();
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
} }
}.execute(); StartupWindowProvider.getInstance().open();
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
} }
/** /**
* A task that refreshes the cases table using a list of auto ingest cases. * Indicates whether or not a time satisfies a time filter defined by this
* panel's time filter radio buttons.
*
* @param currentTime The current date and time in milliseconds from the
* Unix epoch.
* @param inputTime The date and time to be tested as milliseconds from
* the Unix epoch.
*/ */
private class CaseTableRefreshTask implements Runnable { private boolean passesTimeFilter(long currentTime, long inputTime) {
long numberOfUnits = 10;
long multiplier = 1;
if (rbAllCases.isSelected()) {
return true;
} else if (rbMonths.isSelected()) {
multiplier = 31;
} else if (rbWeeks.isSelected()) {
multiplier = 7;
} else if (rbDays.isSelected()) {
multiplier = 1;
}
return ((currentTime - inputTime) / (1000 * 60 * 60 * 24)) < (numberOfUnits * multiplier);
}
private final List<AutoIngestCase> cases; /**
* RowSorter which makes columns whose type is Date to be sorted first in
* Descending order then in Ascending order
*/
private static class RowSorter<M extends DefaultTableModel> extends TableRowSorter<M> {
CaseTableRefreshTask(List<AutoIngestCase> cases) { RowSorter(M tModel) {
setButtons(); super(tModel);
this.cases = cases;
} }
/**
* @inheritDoc
*/
@Override @Override
public void run() { public void toggleSortOrder(int column) {
cases.sort(reverseDateModifiedComparator); if (!this.getModel().getColumnClass(column).equals(Date.class)) {
caseTableModel.setRowCount(0); super.toggleSortOrder(column); //if it isn't a date column perform the regular sorting
long now = new Date().getTime(); } else {
for (AutoIngestCase autoIngestCase : cases) { ArrayList<RowSorter.SortKey> sortKeys = new ArrayList<>(getSortKeys());
if (passesTimeFilter(now, autoIngestCase.getLastAccessedDate().getTime())) { if (sortKeys.isEmpty() || sortKeys.get(0).getColumn() != column) { //sort descending
caseTableModel.addRow(new Object[]{ sortKeys.add(0, new RowSorter.SortKey(column, SortOrder.DESCENDING));
autoIngestCase.getCaseName(), } else if (sortKeys.get(0).getSortOrder() == SortOrder.ASCENDING) {
autoIngestCase.getCreationDate(), sortKeys.removeIf(key -> key.getColumn() == column);
autoIngestCase.getLastAccessedDate(), sortKeys.add(0, new RowSorter.SortKey(column, SortOrder.DESCENDING));
(AutoIngestCase.CaseStatus.OK != autoIngestCase.getStatus()), } else {
autoIngestCase.getCaseDirectoryPath().toString()}); sortKeys.removeIf(key -> key.getColumn() == column);
sortKeys.add(0, new RowSorter.SortKey(column, SortOrder.ASCENDING));
} }
setSortKeys(sortKeys);
} }
setSelectedCase(currentlySelectedCase);
} }
/**
* Indicates whether or not a time satisfies a time filter defined by
* this panel's time filter radio buttons.
*
* @param currentTime The current date and time in milliseconds from the
* Unix epoch.
* @param inputTime The date and time to be tested as milliseconds
* from the Unix epoch.
*/
private boolean passesTimeFilter(long currentTime, long inputTime) {
long numberOfUnits = 10;
long multiplier = 1;
if (rbAllCases.isSelected()) {
return true;
} else if (rbMonths.isSelected()) {
multiplier = 31;
} else if (rbWeeks.isSelected()) {
multiplier = 7;
} else if (rbDays.isSelected()) {
multiplier = 1;
}
return ((currentTime - inputTime) / (1000 * 60 * 60 * 24)) < (numberOfUnits * multiplier);
}
} }
/** /**
@ -443,7 +372,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
setName("Completed Cases"); // NOI18N setName("Completed Cases"); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(bnOpen, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.bnOpen.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnOpen, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.bnOpen.text")); // NOI18N
bnOpen.setEnabled(false); bnOpen.setEnabled(false);
bnOpen.addActionListener(new java.awt.event.ActionListener() { bnOpen.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
@ -451,9 +380,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
} }
}); });
casesTable.setAutoCreateRowSorter(true);
casesTable.setModel(caseTableModel); casesTable.setModel(caseTableModel);
casesTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
casesTable.setRowHeight(20); casesTable.setRowHeight(20);
casesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); casesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
casesTable.addMouseListener(new java.awt.event.MouseAdapter() { casesTable.addMouseListener(new java.awt.event.MouseAdapter() {
@ -463,7 +390,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
}); });
scrollPaneTable.setViewportView(casesTable); scrollPaneTable.setViewportView(casesTable);
org.openide.awt.Mnemonics.setLocalizedText(bnRefresh, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.bnRefresh.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnRefresh, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.bnRefresh.text")); // NOI18N
bnRefresh.addActionListener(new java.awt.event.ActionListener() { bnRefresh.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
bnRefreshActionPerformed(evt); bnRefreshActionPerformed(evt);
@ -472,7 +399,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
rbGroupHistoryLength.add(rbAllCases); rbGroupHistoryLength.add(rbAllCases);
rbAllCases.setSelected(true); rbAllCases.setSelected(true);
org.openide.awt.Mnemonics.setLocalizedText(rbAllCases, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbAllCases.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(rbAllCases, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.rbAllCases.text")); // NOI18N
rbAllCases.addItemListener(new java.awt.event.ItemListener() { rbAllCases.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) { public void itemStateChanged(java.awt.event.ItemEvent evt) {
rbAllCasesItemStateChanged(evt); rbAllCasesItemStateChanged(evt);
@ -494,8 +421,8 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
.addComponent(rbAllCases)) .addComponent(rbAllCases))
); );
org.openide.awt.Mnemonics.setLocalizedText(bnShowLog, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.bnShowLog.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnShowLog, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.bnShowLog.text")); // NOI18N
bnShowLog.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.bnShowLog.toolTipText")); // NOI18N bnShowLog.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.bnShowLog.toolTipText")); // NOI18N
bnShowLog.setEnabled(false); bnShowLog.setEnabled(false);
bnShowLog.addActionListener(new java.awt.event.ActionListener() { bnShowLog.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
@ -504,7 +431,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
}); });
rbGroupHistoryLength.add(rbDays); rbGroupHistoryLength.add(rbDays);
org.openide.awt.Mnemonics.setLocalizedText(rbDays, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbDays.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(rbDays, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.rbDays.text")); // NOI18N
rbDays.setName(""); // NOI18N rbDays.setName(""); // NOI18N
rbDays.addItemListener(new java.awt.event.ItemListener() { rbDays.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) { public void itemStateChanged(java.awt.event.ItemEvent evt) {
@ -513,7 +440,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
}); });
rbGroupHistoryLength.add(rbWeeks); rbGroupHistoryLength.add(rbWeeks);
org.openide.awt.Mnemonics.setLocalizedText(rbWeeks, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbWeeks.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(rbWeeks, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.rbWeeks.text")); // NOI18N
rbWeeks.addItemListener(new java.awt.event.ItemListener() { rbWeeks.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) { public void itemStateChanged(java.awt.event.ItemEvent evt) {
rbWeeksItemStateChanged(evt); rbWeeksItemStateChanged(evt);
@ -521,7 +448,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
}); });
rbGroupHistoryLength.add(rbMonths); rbGroupHistoryLength.add(rbMonths);
org.openide.awt.Mnemonics.setLocalizedText(rbMonths, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbMonths.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(rbMonths, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.rbMonths.text")); // NOI18N
rbMonths.addItemListener(new java.awt.event.ItemListener() { rbMonths.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) { public void itemStateChanged(java.awt.event.ItemEvent evt) {
rbMonthsItemStateChanged(evt); rbMonthsItemStateChanged(evt);
@ -529,7 +456,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
}); });
rbGroupLabel.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N rbGroupLabel.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(rbGroupLabel, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbGroupLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(rbGroupLabel, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.rbGroupLabel.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
@ -556,7 +483,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(bnRefresh) .addComponent(bnRefresh)
.addGap(4, 4, 4)) .addGap(4, 4, 4))
.addComponent(scrollPaneTable, javax.swing.GroupLayout.DEFAULT_SIZE, 1007, Short.MAX_VALUE)) .addComponent(scrollPaneTable))
.addContainerGap()) .addContainerGap())
); );
layout.setVerticalGroup( layout.setVerticalGroup(
@ -588,10 +515,12 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
*/ */
private void bnOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOpenActionPerformed private void bnOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOpenActionPerformed
int modelRow = casesTable.convertRowIndexToModel(casesTable.getSelectedRow()); int modelRow = casesTable.convertRowIndexToModel(casesTable.getSelectedRow());
Path caseMetadataFilePath = Paths.get((String) caseTableModel.getValueAt(modelRow, String caseDirectory = (String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.OUTPUTFOLDER.ordinal());
COLUMN_HEADERS.OUTPUTFOLDER.ordinal()), Path caseMetadataFilePath = Paths.get(caseDirectory, (String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.METADATA_FILE.ordinal()));
caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.CASE.ordinal()) + CaseMetadata.getFileExtension());
openCase(caseMetadataFilePath); new Thread(() -> {
openCase(caseMetadataFilePath);
}).start();
}//GEN-LAST:event_bnOpenActionPerformed }//GEN-LAST:event_bnOpenActionPerformed
/** /**
@ -599,53 +528,50 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
* *
* @param evt -- The event that caused this to be called * @param evt -- The event that caused this to be called
*/ */
private void bnRefreshActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bnRefreshActionPerformed private void bnRefreshActionPerformed(java.awt.event.ActionEvent evt) {
{//GEN-HEADEREND:event_bnRefreshActionPerformed refresh();
updateView(); }
}//GEN-LAST:event_bnRefreshActionPerformed
private void rbDaysItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbDaysItemStateChanged private void rbDaysItemStateChanged(java.awt.event.ItemEvent evt) {
if (rbDays.isSelected()) { if (rbDays.isSelected()) {
updateView(); refresh();
} }
}//GEN-LAST:event_rbDaysItemStateChanged }
private void rbAllCasesItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbAllCasesItemStateChanged private void rbAllCasesItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbAllCasesItemStateChanged
if (rbAllCases.isSelected()) { if (rbAllCases.isSelected()) {
updateView(); refresh();
} }
}//GEN-LAST:event_rbAllCasesItemStateChanged }//GEN-LAST:event_rbAllCasesItemStateChanged
private void rbMonthsItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbMonthsItemStateChanged private void rbMonthsItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbMonthsItemStateChanged
if (rbMonths.isSelected()) { if (rbMonths.isSelected()) {
updateView(); refresh();
} }
}//GEN-LAST:event_rbMonthsItemStateChanged }//GEN-LAST:event_rbMonthsItemStateChanged
private void rbWeeksItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbWeeksItemStateChanged private void rbWeeksItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbWeeksItemStateChanged
if (rbWeeks.isSelected()) { if (rbWeeks.isSelected()) {
updateView(); refresh();
} }
}//GEN-LAST:event_rbWeeksItemStateChanged }//GEN-LAST:event_rbWeeksItemStateChanged
private void bnShowLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnShowLogActionPerformed private void bnShowLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnShowLogActionPerformed
int selectedRow = casesTable.convertRowIndexToModel(casesTable.getSelectedRow()); Path pathToLog = getSelectedCaseLogFilePath();
int rowCount = casesTable.getRowCount(); if (pathToLog != null) {
if (selectedRow >= 0 && selectedRow < rowCount) {
String thePath = (String) caseTableModel.getValueAt(selectedRow, COLUMN_HEADERS.OUTPUTFOLDER.ordinal());
Path pathToLog = AutoIngestJobLogger.getLogPath(Paths.get(thePath));
try { try {
if (pathToLog.toFile().exists()) { if (pathToLog.toFile().exists()) {
Desktop.getDesktop().edit(pathToLog.toFile()); Desktop.getDesktop().edit(pathToLog.toFile());
} else { } else {
JOptionPane.showMessageDialog(this, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "DisplayLogDialog.cannotFindLog"), JOptionPane.showMessageDialog(this, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.cannotFindLog"),
org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "DisplayLogDialog.unableToShowLogFile"), JOptionPane.ERROR_MESSAGE); org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.unableToShowLogFile"), JOptionPane.ERROR_MESSAGE);
} }
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.SEVERE, String.format("Error attempting to open case auto ingest log file %s", pathToLog), ex); LOGGER.log(Level.SEVERE, String.format("Error attempting to open case auto ingest log file %s", pathToLog), ex);
JOptionPane.showMessageDialog(this, JOptionPane.showMessageDialog(this,
org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "DisplayLogDialog.cannotOpenLog"), org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.cannotOpenLog"),
org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "DisplayLogDialog.unableToShowLogFile"), org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.unableToShowLogFile"),
JOptionPane.PLAIN_MESSAGE); JOptionPane.PLAIN_MESSAGE);
} }
} }
@ -654,9 +580,8 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
private void casesTableMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_casesTableMouseClicked private void casesTableMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_casesTableMouseClicked
if (evt.getClickCount() == 2) { if (evt.getClickCount() == 2) {
int modelRow = casesTable.convertRowIndexToModel(casesTable.getSelectedRow()); int modelRow = casesTable.convertRowIndexToModel(casesTable.getSelectedRow());
Path caseMetadataFilePath = Paths.get((String) caseTableModel.getValueAt(modelRow, String caseDirectory = (String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.OUTPUTFOLDER.ordinal());
COLUMN_HEADERS.OUTPUTFOLDER.ordinal()), Path caseMetadataFilePath = Paths.get(caseDirectory, (String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.METADATA_FILE.ordinal()));
caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.CASE.ordinal()) + CaseMetadata.getFileExtension());
openCase(caseMetadataFilePath); openCase(caseMetadataFilePath);
} }
}//GEN-LAST:event_casesTableMouseClicked }//GEN-LAST:event_casesTableMouseClicked

View File

@ -34,7 +34,6 @@ import java.time.LocalDate;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
@ -1251,13 +1250,13 @@ public abstract class AbstractSqlEamDb implements EamDb {
} }
/** /**
* Remove a reference set and all hashes contained in it. * Remove a reference set and all entries contained in it.
* @param referenceSetID * @param referenceSetID
* @throws EamDbException * @throws EamDbException
*/ */
@Override @Override
public void deleteReferenceSet(int referenceSetID) throws EamDbException{ public void deleteReferenceSet(int referenceSetID) throws EamDbException{
deleteReferenceSetFiles(referenceSetID); deleteReferenceSetEntries(referenceSetID);
deleteReferenceSetEntry(referenceSetID); deleteReferenceSetEntry(referenceSetID);
} }
@ -1277,7 +1276,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
preparedStatement.setInt(1, referenceSetID); preparedStatement.setInt(1, referenceSetID);
preparedStatement.executeUpdate(); preparedStatement.executeUpdate();
} catch (SQLException ex) { } catch (SQLException ex) {
throw new EamDbException("Error deleting reference set", ex); // NON-NLS throw new EamDbException("Error deleting reference set " + referenceSetID, ex); // NON-NLS
} finally { } finally {
EamDbUtil.closePreparedStatement(preparedStatement); EamDbUtil.closePreparedStatement(preparedStatement);
EamDbUtil.closeConnection(conn); EamDbUtil.closeConnection(conn);
@ -1285,16 +1284,18 @@ public abstract class AbstractSqlEamDb implements EamDb {
} }
/** /**
* Remove all entries for this reference set from the reference_file table * Remove all entries for this reference set from the reference tables
* (Currently only removes entries from the reference_file table)
* @param referenceSetID * @param referenceSetID
* @throws EamDbException * @throws EamDbException
*/ */
private void deleteReferenceSetFiles(int referenceSetID) throws EamDbException{ private void deleteReferenceSetEntries(int referenceSetID) throws EamDbException{
Connection conn = connect(); Connection conn = connect();
PreparedStatement preparedStatement = null; PreparedStatement preparedStatement = null;
String sql = "DELETE FROM %s WHERE reference_set_id=?"; String sql = "DELETE FROM %s WHERE reference_set_id=?";
// When other reference types are added, this will need to loop over all the tables
String fileTableName = EamDbUtil.correlationTypeToReferenceTableName(getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID)); String fileTableName = EamDbUtil.correlationTypeToReferenceTableName(getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID));
try { try {
@ -1302,7 +1303,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
preparedStatement.setInt(1, referenceSetID); preparedStatement.setInt(1, referenceSetID);
preparedStatement.executeUpdate(); preparedStatement.executeUpdate();
} catch (SQLException ex) { } catch (SQLException ex) {
throw new EamDbException("Error deleting files from reference set", ex); // NON-NLS throw new EamDbException("Error deleting files from reference set " + referenceSetID, ex); // NON-NLS
} finally { } finally {
EamDbUtil.closePreparedStatement(preparedStatement); EamDbUtil.closePreparedStatement(preparedStatement);
EamDbUtil.closeConnection(conn); EamDbUtil.closeConnection(conn);
@ -1310,31 +1311,46 @@ public abstract class AbstractSqlEamDb implements EamDb {
} }
/** /**
* Check whether the given reference set exists in the central repository. * Check whether a reference set with the given parameters exists in the central repository.
* Used to check whether reference sets saved in the settings are still present.
* @param referenceSetID * @param referenceSetID
* @param hashSetName * @param setName
* @param version * @param version
* @return true if a matching entry exists in the central repository * @return true if a matching entry exists in the central repository
* @throws EamDbException * @throws EamDbException
*/ */
@Override @Override
public boolean referenceSetIsValid(int referenceSetID, String hashSetName, String version) throws EamDbException{ public boolean referenceSetIsValid(int referenceSetID, String setName, String version) throws EamDbException{
EamGlobalSet refSet = this.getReferenceSetByID(referenceSetID); EamGlobalSet refSet = this.getReferenceSetByID(referenceSetID);
if(refSet == null){ if(refSet == null){
return false; return false;
} }
return(refSet.getSetName().equals(hashSetName) && refSet.getVersion().equals(version)); return(refSet.getSetName().equals(setName) && refSet.getVersion().equals(version));
} }
/** /**
* Check if the given hash is in a specific reference set * Check if the given file hash is in this reference set.
* Only searches the reference_files table.
* @param hash * @param hash
* @param referenceSetID * @param referenceSetID
* @return true if the hash is found in the reference set * @return true if the hash is found in the reference set
* @throws EamDbException
*/ */
@Override @Override
public boolean isHashInReferenceSet(String hash, int referenceSetID) throws EamDbException{ public boolean isFileHashInReferenceSet(String hash, int referenceSetID) throws EamDbException{
return isValueInReferenceSet(hash, referenceSetID, CorrelationAttribute.FILES_TYPE_ID);
}
/**
* Check if the given value is in a specific reference set
* @param value
* @param referenceSetID
* @param correlationTypeID
* @return true if the value is found in the reference set
*/
@Override
public boolean isValueInReferenceSet(String value, int referenceSetID, int correlationTypeID) throws EamDbException{
Connection conn = connect(); Connection conn = connect();
@ -1343,17 +1359,17 @@ public abstract class AbstractSqlEamDb implements EamDb {
ResultSet resultSet = null; ResultSet resultSet = null;
String sql = "SELECT count(*) FROM %s WHERE value=? AND reference_set_id=?"; String sql = "SELECT count(*) FROM %s WHERE value=? AND reference_set_id=?";
String fileTableName = EamDbUtil.correlationTypeToReferenceTableName(getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID)); String fileTableName = EamDbUtil.correlationTypeToReferenceTableName(getCorrelationTypeById(correlationTypeID));
try { try {
preparedStatement = conn.prepareStatement(String.format(sql, fileTableName)); preparedStatement = conn.prepareStatement(String.format(sql, fileTableName));
preparedStatement.setString(1, hash); preparedStatement.setString(1, value);
preparedStatement.setInt(2, referenceSetID); preparedStatement.setInt(2, referenceSetID);
resultSet = preparedStatement.executeQuery(); resultSet = preparedStatement.executeQuery();
resultSet.next(); resultSet.next();
matchingInstances = resultSet.getLong(1); matchingInstances = resultSet.getLong(1);
} catch (SQLException ex) { } catch (SQLException ex) {
throw new EamDbException("Error determining if file is in reference set.", ex); // NON-NLS throw new EamDbException("Error determining if value (" + value + ") is in reference set " + referenceSetID, ex); // NON-NLS
} finally { } finally {
EamDbUtil.closePreparedStatement(preparedStatement); EamDbUtil.closePreparedStatement(preparedStatement);
EamDbUtil.closeResultSet(resultSet); EamDbUtil.closeResultSet(resultSet);
@ -1372,7 +1388,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
* @return Global known status of the artifact * @return Global known status of the artifact
*/ */
@Override @Override
public boolean isArtifactlKnownBadByReference(CorrelationAttribute.Type aType, String value) throws EamDbException { public boolean isArtifactKnownBadByReference(CorrelationAttribute.Type aType, String value) throws EamDbException {
// TEMP: Only support file correlation type // TEMP: Only support file correlation type
if (aType.getId() != CorrelationAttribute.FILES_TYPE_ID) { if (aType.getId() != CorrelationAttribute.FILES_TYPE_ID) {
@ -1522,30 +1538,6 @@ public abstract class AbstractSqlEamDb implements EamDb {
return (getOrganizationByID(globalSet.getOrgID())); return (getOrganizationByID(globalSet.getOrgID()));
} }
/**
* Add a new reference set
*
* @param orgID
* @param setName
* @param version
* @param importDate
* @return the reference set ID of the newly created set
* @throws EamDbException
*/
@Override
public int newReferenceSet(int orgID, String setName, String version, TskData.FileKnown knownStatus,
boolean isReadOnly) throws EamDbException {
EamDb dbManager = EamDb.getInstance();
EamGlobalSet eamGlobalSet = new EamGlobalSet(
orgID,
setName,
version,
knownStatus,
isReadOnly,
LocalDate.now());
return dbManager.newReferencelSet(eamGlobalSet);
}
/** /**
* Update an existing organization. * Update an existing organization.
* *
@ -1618,7 +1610,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
* @throws EamDbException * @throws EamDbException
*/ */
@Override @Override
public int newReferencelSet(EamGlobalSet eamGlobalSet) throws EamDbException { public int newReferenceSet(EamGlobalSet eamGlobalSet) throws EamDbException {
Connection conn = connect(); Connection conn = connect();
PreparedStatement preparedStatement1 = null; PreparedStatement preparedStatement1 = null;
@ -1757,14 +1749,15 @@ public abstract class AbstractSqlEamDb implements EamDb {
} }
/** /**
* Check whether a reference set with the given name/version is in the central repo * Check whether a reference set with the given name/version is in the central repo.
* @param hashSetName * Used to check for name collisions when creating reference sets.
* @param referenceSetName
* @param version * @param version
* @return true if a matching set is found * @return true if a matching set is found
* @throws EamDbException * @throws EamDbException
*/ */
@Override @Override
public boolean referenceSetExists(String hashSetName, String version) throws EamDbException{ public boolean referenceSetExists(String referenceSetName, String version) throws EamDbException{
Connection conn = connect(); Connection conn = connect();
PreparedStatement preparedStatement1 = null; PreparedStatement preparedStatement1 = null;
@ -1773,13 +1766,14 @@ public abstract class AbstractSqlEamDb implements EamDb {
try { try {
preparedStatement1 = conn.prepareStatement(sql1); preparedStatement1 = conn.prepareStatement(sql1);
preparedStatement1.setString(1, hashSetName); preparedStatement1.setString(1, referenceSetName);
preparedStatement1.setString(2, version); preparedStatement1.setString(2, version);
resultSet = preparedStatement1.executeQuery(); resultSet = preparedStatement1.executeQuery();
return (resultSet.next()); return (resultSet.next());
} catch (SQLException ex) { } catch (SQLException ex) {
throw new EamDbException("Error getting reference instances by type and value.", ex); // NON-NLS throw new EamDbException("Error testing whether reference set exists (name: " + referenceSetName
+ " version: " + version, ex); // NON-NLS
} finally { } finally {
EamDbUtil.closePreparedStatement(preparedStatement1); EamDbUtil.closePreparedStatement(preparedStatement1);
EamDbUtil.closeResultSet(resultSet); EamDbUtil.closeResultSet(resultSet);

View File

@ -362,38 +362,51 @@ public interface EamDb {
List<String> getListCasesHavingArtifactInstancesKnownBad(CorrelationAttribute.Type aType, String value) throws EamDbException; List<String> getListCasesHavingArtifactInstancesKnownBad(CorrelationAttribute.Type aType, String value) throws EamDbException;
/** /**
* Remove a reference set and all hashes contained in it. * Remove a reference set and all values contained in it.
* @param referenceSetID * @param referenceSetID
* @throws EamDbException * @throws EamDbException
*/ */
public void deleteReferenceSet(int referenceSetID) throws EamDbException; public void deleteReferenceSet(int referenceSetID) throws EamDbException;
/** /**
* Check whether the given reference set exists in the central repository. * Check whether a reference set with the given parameters exists in the central repository.
* Used to check whether reference sets saved in the settings are still present.
* @param referenceSetID * @param referenceSetID
* @param hashSetName * @param referenceSetName
* @param version * @param version
* @return true if a matching entry exists in the central repository * @return true if a matching entry exists in the central repository
* @throws EamDbException * @throws EamDbException
*/ */
public boolean referenceSetIsValid(int referenceSetID, String hashSetName, String version) throws EamDbException; public boolean referenceSetIsValid(int referenceSetID, String referenceSetName, String version) throws EamDbException;
/** /**
* Check whether a reference set with the given name/version is in the central repo * Check whether a reference set with the given name/version is in the central repo.
* @param hashSetName * Used to check for name collisions when creating reference sets.
* @param referenceSetName
* @param version * @param version
* @return true if a matching set is found * @return true if a matching set is found
* @throws EamDbException * @throws EamDbException
*/ */
public boolean referenceSetExists(String hashSetName, String version) throws EamDbException; public boolean referenceSetExists(String referenceSetName, String version) throws EamDbException;
/** /**
* Check if the given hash is in a specific reference set * Check if the given file hash is in this reference set.
* Only searches the reference_files table.
* @param hash * @param hash
* @param referenceSetID * @param referenceSetID
* @return true if the hash is found in the reference set * @return true if the hash is found in the reference set
* @throws EamDbException
*/ */
public boolean isHashInReferenceSet(String hash, int referenceSetID) throws EamDbException; public boolean isFileHashInReferenceSet(String hash, int referenceSetID) throws EamDbException;
/**
* Check if the given value is in a specific reference set
* @param value
* @param referenceSetID
* @param correlationTypeID
* @return true if the hash is found in the reference set
*/
public boolean isValueInReferenceSet(String value, int referenceSetID, int correlationTypeID) throws EamDbException;
/** /**
* Is the artifact known as bad according to the reference entries? * Is the artifact known as bad according to the reference entries?
@ -403,7 +416,7 @@ public interface EamDb {
* *
* @return Global known status of the artifact * @return Global known status of the artifact
*/ */
boolean isArtifactlKnownBadByReference(CorrelationAttribute.Type aType, String value) throws EamDbException; boolean isArtifactKnownBadByReference(CorrelationAttribute.Type aType, String value) throws EamDbException;
/** /**
* Add a new organization * Add a new organization
@ -472,20 +485,7 @@ public interface EamDb {
* *
* @throws EamDbException * @throws EamDbException
*/ */
int newReferencelSet(EamGlobalSet eamGlobalSet) throws EamDbException; int newReferenceSet(EamGlobalSet eamGlobalSet) throws EamDbException;
/**
* Add a new reference set
*
* @param orgID
* @param setName
* @param version
* @param importDate
* @return the reference set ID of the newly created set
* @throws EamDbException
*/
int newReferenceSet(int orgID, String setName, String version, TskData.FileKnown knownStatus,
boolean isReadOnly) throws EamDbException;
/** /**
* Get a global set by ID * Get a global set by ID

View File

@ -19,7 +19,6 @@
package org.sleuthkit.autopsy.centralrepository.datamodel; package org.sleuthkit.autopsy.centralrepository.datamodel;
import java.time.LocalDate; import java.time.LocalDate;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager;
import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskData;
/** /**
@ -62,6 +61,26 @@ public class EamGlobalSet {
this(-1, orgID, setName, version, knownStatus, isReadOnly, importDate); this(-1, orgID, setName, version, knownStatus, isReadOnly, importDate);
} }
/**
* Create a new EamGlobalSet object.
* This is intended to be used when creating a new global set as the
* globalSetID will be unknown to start.
* importDate will be automatically set to the current time.
* @param orgID
* @param setName
* @param version
* @param knownStatus
* @param isReadOnly
*/
public EamGlobalSet(
int orgID,
String setName,
String version,
TskData.FileKnown knownStatus,
boolean isReadOnly) {
this(-1, orgID, setName, version, knownStatus, isReadOnly, LocalDate.now());
}
/** /**
* @return the globalSetID * @return the globalSetID
*/ */
@ -146,17 +165,6 @@ public class EamGlobalSet {
this.fileKnownStatus = fileKnownStatus; this.fileKnownStatus = fileKnownStatus;
} }
/**
* Return the FileKnown status as a KnownFilesType
* @return KNOWN or KNOWN_BAD
*/
public HashDbManager.HashDb.KnownFilesType getKnownStatus(){
if(fileKnownStatus.equals(TskData.FileKnown.BAD)){
return HashDbManager.HashDb.KnownFilesType.KNOWN_BAD;
}
return HashDbManager.HashDb.KnownFilesType.KNOWN;
}
/** /**
* @return the importDate * @return the importDate
*/ */

View File

@ -636,7 +636,7 @@ public class SqliteEamDb extends AbstractSqlEamDb {
} }
/** /**
* Remove a reference set and all hashes contained in it. * Remove a reference set and all values contained in it.
* @param referenceSetID * @param referenceSetID
* @throws EamDbException * @throws EamDbException
*/ */
@ -657,27 +657,28 @@ public class SqliteEamDb extends AbstractSqlEamDb {
* @return true if the hash is found in the reference set * @return true if the hash is found in the reference set
*/ */
@Override @Override
public boolean isHashInReferenceSet(String hash, int referenceSetID) throws EamDbException{ public boolean isValueInReferenceSet(String value, int referenceSetID, int correlationTypeID) throws EamDbException {
try{ try{
acquireSharedLock(); acquireSharedLock();
return super.isHashInReferenceSet(hash, referenceSetID); return super.isValueInReferenceSet(value, referenceSetID, correlationTypeID);
} finally { } finally {
releaseSharedLock(); releaseSharedLock();
} }
} }
/** /**
* Check whether a reference set with the given name/version is in the central repo * Check whether a reference set with the given name/version is in the central repo.
* @param hashSetName * Used to check for name collisions when creating reference sets.
* @param referenceSetName
* @param version * @param version
* @return true if a matching set is found * @return true if a matching set is found
* @throws EamDbException * @throws EamDbException
*/ */
@Override @Override
public boolean referenceSetExists(String hashSetName, String version) throws EamDbException { public boolean referenceSetExists(String referenceSetName, String version) throws EamDbException {
try{ try{
acquireSharedLock(); acquireSharedLock();
return super.referenceSetExists(hashSetName, version); return super.referenceSetExists(referenceSetName, version);
} finally { } finally {
releaseSharedLock(); releaseSharedLock();
} }
@ -692,10 +693,10 @@ public class SqliteEamDb extends AbstractSqlEamDb {
* @return Global known status of the artifact * @return Global known status of the artifact
*/ */
@Override @Override
public boolean isArtifactlKnownBadByReference(CorrelationAttribute.Type aType, String value) throws EamDbException { public boolean isArtifactKnownBadByReference(CorrelationAttribute.Type aType, String value) throws EamDbException {
try{ try{
acquireSharedLock(); acquireSharedLock();
return super.isArtifactlKnownBadByReference(aType, value); return super.isArtifactKnownBadByReference(aType, value);
} finally { } finally {
releaseSharedLock(); releaseSharedLock();
} }
@ -785,10 +786,10 @@ public class SqliteEamDb extends AbstractSqlEamDb {
* @throws EamDbException * @throws EamDbException
*/ */
@Override @Override
public int newReferencelSet(EamGlobalSet eamGlobalSet) throws EamDbException { public int newReferenceSet(EamGlobalSet eamGlobalSet) throws EamDbException {
try{ try{
acquireExclusiveLock(); acquireExclusiveLock();
return super.newReferencelSet(eamGlobalSet); return super.newReferenceSet(eamGlobalSet);
} finally { } finally {
releaseExclusiveLock(); releaseExclusiveLock();
} }

View File

@ -0,0 +1,141 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 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.coordinationservice;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
/**
* An object that converts case data for a case directory coordination service
* node to and from byte arrays.
*/
public final class CaseNodeData {
private static final int CURRENT_VERSION = 0;
private int version;
private boolean errorsOccurred;
/**
* Gets the current version of the case directory coordination service node
* data.
*
* @return The version number.
*/
public static int getCurrentVersion() {
return CaseNodeData.CURRENT_VERSION;
}
/**
* Uses coordination service node data to construct an object that converts
* case data for a case directory coordination service node to and from byte
* arrays.
*
* @param nodeData The raw bytes received from the coordination service.
*
* @throws InvalidDataException If the node data buffer is smaller than
* expected.
*/
public CaseNodeData(byte[] nodeData) throws InvalidDataException {
if(nodeData == null || nodeData.length == 0) {
this.version = CURRENT_VERSION;
this.errorsOccurred = false;
} else {
/*
* Get fields from node data.
*/
ByteBuffer buffer = ByteBuffer.wrap(nodeData);
try {
if (buffer.hasRemaining()) {
this.version = buffer.getInt();
/*
* Flags bit format: 76543210
* 0-6 --> reserved for future use
* 7 --> errorsOccurred
*/
byte flags = buffer.get();
this.errorsOccurred = (flags < 0);
}
} catch (BufferUnderflowException ex) {
throw new InvalidDataException("Node data is incomplete", ex);
}
}
}
/**
* Gets whether or not any errors occurred during the processing of the job.
*
* @return True or false.
*/
public boolean getErrorsOccurred() {
return this.errorsOccurred;
}
/**
* Sets whether or not any errors occurred during the processing of job.
*
* @param errorsOccurred True or false.
*/
public void setErrorsOccurred(boolean errorsOccurred) {
this.errorsOccurred = errorsOccurred;
}
/**
* Gets the node data version number.
*
* @return The version number.
*/
public int getVersion() {
return this.version;
}
/**
* Gets the node data as a byte array that can be sent to the coordination
* service.
*
* @return The node data as a byte array.
*/
public byte[] toArray() {
ByteBuffer buffer = ByteBuffer.allocate(5);
buffer.putInt(this.version);
buffer.put((byte)(this.errorsOccurred ? 0x80 : 0));
// Prepare the array
byte[] array = new byte[buffer.position()];
buffer.rewind();
buffer.get(array, 0, array.length);
return array;
}
public final static class InvalidDataException extends Exception {
private static final long serialVersionUID = 1L;
private InvalidDataException(String message) {
super(message);
}
private InvalidDataException(String message, Throwable cause) {
super(message, cause);
}
}
}

View File

@ -29,15 +29,15 @@ import java.util.logging.Handler;
import java.util.logging.Level; import java.util.logging.Level;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.embed.swing.JFXPanel; import javafx.embed.swing.JFXPanel;
import javax.swing.SwingWorker;
import org.openide.LifecycleManager;
import org.openide.modules.ModuleInstall; import org.openide.modules.ModuleInstall;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.windows.WindowManager; import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.actions.IngestRunningCheck; import org.sleuthkit.autopsy.actions.IngestRunningCheck;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import static org.sleuthkit.autopsy.core.UserPreferences.SETTINGS_PROPERTIES;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil;
/** /**
@ -207,6 +207,9 @@ public class Installer extends ModuleInstall {
System.setProperty("sun.java2d.dpiaware", "false"); System.setProperty("sun.java2d.dpiaware", "false");
System.setProperty("prism.allowhidpi", "false"); System.setProperty("prism.allowhidpi", "false");
// Update existing configuration in case of unsupported settings
updateConfig();
packageInstallers = new ArrayList<>(); packageInstallers = new ArrayList<>();
packageInstallers.add(org.sleuthkit.autopsy.coreutils.Installer.getDefault()); packageInstallers.add(org.sleuthkit.autopsy.coreutils.Installer.getDefault());
packageInstallers.add(org.sleuthkit.autopsy.corecomponents.Installer.getDefault()); packageInstallers.add(org.sleuthkit.autopsy.corecomponents.Installer.getDefault());
@ -215,6 +218,21 @@ public class Installer extends ModuleInstall {
packageInstallers.add(org.sleuthkit.autopsy.centralrepository.eventlisteners.Installer.getDefault()); packageInstallers.add(org.sleuthkit.autopsy.centralrepository.eventlisteners.Installer.getDefault());
} }
/**
* If the mode in the configuration file is 'REVIEW' (2, now invalid), this
* method will set it to 'STANDALONE' (0) and disable auto ingest.
*/
private void updateConfig() {
String mode = ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, "AutopsyMode");
if(mode != null) {
int ordinal = Integer.parseInt(mode);
if(ordinal > 1) {
UserPreferences.setMode(UserPreferences.SelectedMode.STANDALONE);
ModuleSettings.setConfigSetting(UserPreferences.SETTINGS_PROPERTIES, "JoinAutoModeCluster", Boolean.toString(false));
}
}
}
/** /**
* Check if JavaFx initialized * Check if JavaFx initialized
* *

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2014 Basis Technology Corp. * Copyright 2014-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -23,7 +23,6 @@ import java.util.prefs.BackingStoreException;
import org.sleuthkit.autopsy.events.MessageServiceConnectionInfo; import org.sleuthkit.autopsy.events.MessageServiceConnectionInfo;
import java.util.prefs.PreferenceChangeListener; import java.util.prefs.PreferenceChangeListener;
import java.util.prefs.Preferences; import java.util.prefs.Preferences;
import org.openide.util.Exceptions;
import org.openide.util.NbPreferences; import org.openide.util.NbPreferences;
import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil;
@ -76,8 +75,7 @@ public final class UserPreferences {
public enum SelectedMode { public enum SelectedMode {
STANDALONE, STANDALONE,
AUTOINGEST, AUTOINGEST
REVIEW
}; };
/** /**

View File

@ -51,7 +51,7 @@
<file name="org-sleuthkit-autopsy-casemodule-CaseDeleteAction.instance"/> <file name="org-sleuthkit-autopsy-casemodule-CaseDeleteAction.instance"/>
<file name="org-sleuthkit-autopsy-casemodule-CaseOpenAction.instance"> <file name="org-sleuthkit-autopsy-casemodule-CaseOpenAction.instance">
<attr name="delegate" newvalue="org.sleuthkit.autopsy.casemodule.CaseOpenAction"/> <attr name="delegate" newvalue="org.sleuthkit.autopsy.casemodule.CaseOpenAction"/>
<attr name="displayName" bundlevalue="org.sleuthkit.autopsy.casemodule.Bundle#CTL_OpenAction"/> <attr name="displayName" bundlevalue="org.sleuthkit.autopsy.casemodule.Bundle#CTL_CaseOpenAction"/>
<attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/> <attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/>
<attr name="noIconInMenu" boolvalue="false"/> <attr name="noIconInMenu" boolvalue="false"/>
</file> </file>
@ -157,7 +157,7 @@
<attr name="position" intvalue="101"/> <attr name="position" intvalue="101"/>
</file> </file>
<folder name="Open Recent Case"> <folder name="Open Recent Case">
<attr name="position" intvalue="102"/> <attr name="position" intvalue="103"/>
<attr name="SystemFileSystem.localizingBundle" stringvalue="org.sleuthkit.autopsy.casemodule.Bundle"/> <attr name="SystemFileSystem.localizingBundle" stringvalue="org.sleuthkit.autopsy.casemodule.Bundle"/>
<file name="org-sleuthkit-autopsy-casemodule-RecentCasesAction.shadow"> <file name="org-sleuthkit-autopsy-casemodule-RecentCasesAction.shadow">
<attr name="originalFile" stringvalue="Actions/Case/org-sleuthkit-autopsy-casemodule-RecentCases.instance"/> <attr name="originalFile" stringvalue="Actions/Case/org-sleuthkit-autopsy-casemodule-RecentCases.instance"/>
@ -165,11 +165,11 @@
</folder> </folder>
<file name="org-sleuthkit-autopsy-casemodule-CaseCloseAct.shadow"> <file name="org-sleuthkit-autopsy-casemodule-CaseCloseAct.shadow">
<attr name="originalFile" stringvalue="Actions/Case/org-sleuthkit-autopsy-casemodule-CaseCloseAction.instance"/> <attr name="originalFile" stringvalue="Actions/Case/org-sleuthkit-autopsy-casemodule-CaseCloseAction.instance"/>
<attr name="position" intvalue="103"/> <attr name="position" intvalue="104"/>
</file> </file>
<file name="org-sleuthkit-autopsy-casemodule-CaseDeleteAction.shadow"> <file name="org-sleuthkit-autopsy-casemodule-CaseDeleteAction.shadow">
<attr name="originalFile" stringvalue="Actions/Case/org-sleuthkit-autopsy-casemodule-CaseDeleteAction.instance"/> <attr name="originalFile" stringvalue="Actions/Case/org-sleuthkit-autopsy-casemodule-CaseDeleteAction.instance"/>
<attr name="position" intvalue="104"/> <attr name="position" intvalue="105"/>
</file> </file>
<file name="org-sleuthkit-autopsy-casemodule-AddImage-separatorBefore.instance"> <file name="org-sleuthkit-autopsy-casemodule-AddImage-separatorBefore.instance">
<attr name="instanceClass" stringvalue="javax.swing.JSeparator"/> <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2015 Basis Technology Corp. * Copyright 2015-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.experimental.autoingest; package org.sleuthkit.autopsy.coreutils;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Calendar; import java.util.Calendar;
@ -24,32 +24,32 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
/** /**
* Utility methods for working with strings with the time-stamp suffixes used by * Utility methods for working with time stamps of the form
* auto ingest. * 'yyyy_MM_dd_HH_mm_ss'.
*/ */
public final class TimeStampUtils { public final class TimeStampUtils {
/* /*
* Sample time stamp suffix: 2015_02_02_12_10_31 * Sample time stamp suffix: 2015_02_02_12_10_31
*/ */
private static final Pattern timeStampPattern = Pattern.compile("\\d{4}_\\d{2}_\\d{2}_\\d{2}_\\d{2}_\\d{2}$"); private static final Pattern TIME_STAMP_PATTERN = Pattern.compile("\\d{4}_\\d{2}_\\d{2}_\\d{2}_\\d{2}_\\d{2}$");
private static final int LENGTH_OF_DATE_TIME_STAMP = 20; // length of the above time stamp private static final int LENGTH_OF_DATE_TIME_STAMP = 20; // length of the above time stamp
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss"); private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
/** /**
* Checks whether a string ends with an auto ingest time stamp. * Checks whether a string ends with a time stamp.
* *
* @param inputString The string to check. * @param inputString The string to check.
* *
* @return True or false. * @return True or false.
*/ */
public static boolean endsWithTimeStamp(String inputString) { public static boolean endsWithTimeStamp(String inputString) {
Matcher m = timeStampPattern.matcher(inputString); Matcher m = TIME_STAMP_PATTERN.matcher(inputString);
return m.find(); return m.find();
} }
/** /**
* Gets the fixed length of the auto-ingest time stamp suffix. * Gets the fixed length of the time stamp suffix.
* *
* @return The length. * @return The length.
*/ */
@ -58,16 +58,16 @@ public final class TimeStampUtils {
} }
/** /**
* Creates an auto ingest time stamp suffix using the current time. * Creates a time stamp suffix using the current time.
* *
* @return The suffix. * @return The suffix.
*/ */
public static String createTimeStamp() { public static String createTimeStamp() {
return dateFormat.format(Calendar.getInstance().getTime()); return DATE_FORMAT.format(Calendar.getInstance().getTime());
} }
/** /**
* Removes an auto ingest timestamp suffix, if it present. * Removes the time stamp suffix from a string, if present.
* *
* @param inputString The string to trim. * @param inputString The string to trim.
* *
@ -82,7 +82,7 @@ public final class TimeStampUtils {
} }
/** /**
* Gets the auto ingest time stamp suffix from a string, if it is present. * Gets the time stamp suffix from a string, if present.
* *
* @param inputString the name to check for a timestamp * @param inputString the name to check for a timestamp
* *

View File

@ -3,7 +3,7 @@
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> <Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<Properties> <Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[750, 500]"/> <Dimension value="[701, 453]"/>
</Property> </Property>
</Properties> </Properties>
<AuxValues> <AuxValues>
@ -32,19 +32,24 @@
</Layout> </Layout>
<SubComponents> <SubComponents>
<Container class="javax.swing.JPanel" name="jPanel1"> <Container class="javax.swing.JPanel" name="jPanel1">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[701, 453]"/>
</Property>
</Properties>
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="externalViewerTitleLabel" pref="777" max="32767" attributes="0"/> <Component id="externalViewerTitleLabel" pref="681" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
</Group> </Group>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0"> <Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="777" max="32767" attributes="0"/> <Component id="jScrollPane1" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
@ -55,7 +60,7 @@
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="externalViewerTitleLabel" min="-2" max="-2" attributes="0"/> <Component id="externalViewerTitleLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="475" max="32767" attributes="0"/> <EmptySpace pref="428" max="32767" attributes="0"/>
</Group> </Group>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0"> <Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" attributes="0"> <Group type="102" attributes="0">
@ -81,13 +86,18 @@
<SubComponents> <SubComponents>
<Container class="javax.swing.JSplitPane" name="jSplitPane1"> <Container class="javax.swing.JSplitPane" name="jSplitPane1">
<Properties> <Properties>
<Property name="dividerLocation" type="int" value="350"/> <Property name="dividerLocation" type="int" value="365"/>
<Property name="dividerSize" type="int" value="1"/> <Property name="dividerSize" type="int" value="1"/>
</Properties> </Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/> <Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
<SubComponents> <SubComponents>
<Container class="javax.swing.JPanel" name="exePanel"> <Container class="javax.swing.JPanel" name="exePanel">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[311, 224]"/>
</Property>
</Properties>
<Constraints> <Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription"> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="right"/> <JSplitPaneConstraints position="right"/>
@ -103,7 +113,7 @@
<Component id="exePathLabel" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="exePathLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="exePathNameLabel" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="exePathNameLabel" alignment="0" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace pref="159" max="32767" attributes="0"/> <EmptySpace pref="47" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -114,7 +124,7 @@
<Component id="exePathLabel" min="-2" max="-2" attributes="0"/> <Component id="exePathLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="exePathNameLabel" min="-2" max="-2" attributes="0"/> <Component id="exePathNameLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="408" max="32767" attributes="0"/> <EmptySpace pref="361" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -137,6 +147,11 @@
</SubComponents> </SubComponents>
</Container> </Container>
<Container class="javax.swing.JPanel" name="rulesPanel"> <Container class="javax.swing.JPanel" name="rulesPanel">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[365, 406]"/>
</Property>
</Properties>
<Constraints> <Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription"> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="left"/> <JSplitPaneConstraints position="left"/>
@ -149,42 +164,35 @@
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0"> <Component id="ruleListLabel" max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Component id="rulesScrollPane" min="-2" pref="345" max="-2" attributes="0"/>
<Component id="ruleListLabel" alignment="1" max="32767" attributes="0"/> <Group type="102" alignment="1" attributes="0">
<Group type="102" attributes="0"> <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="rulesScrollPane" min="-2" pref="311" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Component id="newRuleButton" min="-2" max="-2" attributes="0"/> <Component id="newRuleButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="editRuleButton" min="-2" max="-2" attributes="0"/> <Component id="editRuleButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="deleteRuleButton" min="-2" max="-2" attributes="0"/> <Component id="deleteRuleButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="ruleListLabel" min="-2" max="-2" attributes="0"/> <Component id="ruleListLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="rulesScrollPane" pref="380" max="32767" attributes="0"/> <Component id="rulesScrollPane" pref="328" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
<Component id="newRuleButton" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="newRuleButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="editRuleButton" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="editRuleButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="deleteRuleButton" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="deleteRuleButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -224,6 +232,15 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.newRuleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.newRuleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newRuleButtonActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newRuleButtonActionPerformed"/>
@ -237,6 +254,15 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.editRuleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.editRuleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="editRuleButtonActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="editRuleButtonActionPerformed"/>
@ -250,6 +276,15 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.deleteRuleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.deleteRuleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteRuleButtonActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteRuleButtonActionPerformed"/>

View File

@ -93,13 +93,17 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
editRuleButton = new javax.swing.JButton(); editRuleButton = new javax.swing.JButton();
deleteRuleButton = new javax.swing.JButton(); deleteRuleButton = new javax.swing.JButton();
setPreferredSize(new java.awt.Dimension(750, 500)); setPreferredSize(new java.awt.Dimension(701, 453));
jPanel1.setPreferredSize(new java.awt.Dimension(701, 453));
org.openide.awt.Mnemonics.setLocalizedText(externalViewerTitleLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.externalViewerTitleLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(externalViewerTitleLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.externalViewerTitleLabel.text")); // NOI18N
jSplitPane1.setDividerLocation(350); jSplitPane1.setDividerLocation(365);
jSplitPane1.setDividerSize(1); jSplitPane1.setDividerSize(1);
exePanel.setPreferredSize(new java.awt.Dimension(311, 224));
org.openide.awt.Mnemonics.setLocalizedText(exePathLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.exePathLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(exePathLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.exePathLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(exePathNameLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.exePathNameLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(exePathNameLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.exePathNameLabel.text")); // NOI18N
@ -113,7 +117,7 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
.addGroup(exePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(exePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(exePathLabel) .addComponent(exePathLabel)
.addComponent(exePathNameLabel)) .addComponent(exePathNameLabel))
.addContainerGap(159, Short.MAX_VALUE)) .addContainerGap(47, Short.MAX_VALUE))
); );
exePanelLayout.setVerticalGroup( exePanelLayout.setVerticalGroup(
exePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) exePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -122,17 +126,22 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
.addComponent(exePathLabel) .addComponent(exePathLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(exePathNameLabel) .addComponent(exePathNameLabel)
.addContainerGap(408, Short.MAX_VALUE)) .addContainerGap(361, Short.MAX_VALUE))
); );
jSplitPane1.setRightComponent(exePanel); jSplitPane1.setRightComponent(exePanel);
rulesPanel.setPreferredSize(new java.awt.Dimension(365, 406));
org.openide.awt.Mnemonics.setLocalizedText(ruleListLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.ruleListLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(ruleListLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.ruleListLabel.text")); // NOI18N
rulesScrollPane.setViewportView(rulesList); rulesScrollPane.setViewportView(rulesList);
newRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add16.png"))); // NOI18N newRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add16.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(newRuleButton, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.newRuleButton.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(newRuleButton, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.newRuleButton.text")); // NOI18N
newRuleButton.setMaximumSize(new java.awt.Dimension(111, 25));
newRuleButton.setMinimumSize(new java.awt.Dimension(111, 25));
newRuleButton.setPreferredSize(new java.awt.Dimension(111, 25));
newRuleButton.addActionListener(new java.awt.event.ActionListener() { newRuleButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
newRuleButtonActionPerformed(evt); newRuleButtonActionPerformed(evt);
@ -141,6 +150,9 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
editRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/edit16.png"))); // NOI18N editRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/edit16.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(editRuleButton, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.editRuleButton.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(editRuleButton, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.editRuleButton.text")); // NOI18N
editRuleButton.setMaximumSize(new java.awt.Dimension(111, 25));
editRuleButton.setMinimumSize(new java.awt.Dimension(111, 25));
editRuleButton.setPreferredSize(new java.awt.Dimension(111, 25));
editRuleButton.addActionListener(new java.awt.event.ActionListener() { editRuleButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
editRuleButtonActionPerformed(evt); editRuleButtonActionPerformed(evt);
@ -149,6 +161,9 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
deleteRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/delete16.png"))); // NOI18N deleteRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/delete16.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(deleteRuleButton, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.deleteRuleButton.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(deleteRuleButton, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.deleteRuleButton.text")); // NOI18N
deleteRuleButton.setMaximumSize(new java.awt.Dimension(111, 25));
deleteRuleButton.setMinimumSize(new java.awt.Dimension(111, 25));
deleteRuleButton.setPreferredSize(new java.awt.Dimension(111, 25));
deleteRuleButton.addActionListener(new java.awt.event.ActionListener() { deleteRuleButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
deleteRuleButtonActionPerformed(evt); deleteRuleButtonActionPerformed(evt);
@ -162,20 +177,16 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
.addGroup(rulesPanelLayout.createSequentialGroup() .addGroup(rulesPanelLayout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(rulesPanelLayout.createSequentialGroup() .addComponent(ruleListLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(rulesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 345, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(ruleListLabel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, rulesPanelLayout.createSequentialGroup()
.addGroup(rulesPanelLayout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE)
.addComponent(rulesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 311, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(newRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
.addGroup(rulesPanelLayout.createSequentialGroup()
.addComponent(newRuleButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(editRuleButton) .addComponent(editRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(deleteRuleButton) .addComponent(deleteRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(0, 0, Short.MAX_VALUE)))) .addContainerGap())
); );
rulesPanelLayout.setVerticalGroup( rulesPanelLayout.setVerticalGroup(
rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -183,12 +194,12 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
.addContainerGap() .addContainerGap()
.addComponent(ruleListLabel) .addComponent(ruleListLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(rulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE) .addComponent(rulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 328, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(newRuleButton) .addComponent(newRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(editRuleButton) .addComponent(editRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(deleteRuleButton)) .addComponent(deleteRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap()) .addContainerGap())
); );
@ -202,12 +213,12 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(externalViewerTitleLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 777, Short.MAX_VALUE) .addComponent(externalViewerTitleLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 681, Short.MAX_VALUE)
.addContainerGap()) .addContainerGap())
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 777, Short.MAX_VALUE) .addComponent(jScrollPane1)
.addContainerGap())) .addContainerGap()))
); );
jPanel1Layout.setVerticalGroup( jPanel1Layout.setVerticalGroup(
@ -215,7 +226,7 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(externalViewerTitleLabel) .addComponent(externalViewerTitleLabel)
.addContainerGap(475, Short.MAX_VALUE)) .addContainerGap(428, Short.MAX_VALUE))
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addGap(32, 32, 32) .addGap(32, 32, 32)

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2015 Basis Technology Corp. * Copyright 2015-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.experimental.autoingest; package org.sleuthkit.autopsy.guiutils;
import static javax.swing.SwingConstants.CENTER; import static javax.swing.SwingConstants.CENTER;

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2015 Basis Technology Corp. * Copyright 2015-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -16,8 +16,9 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.experimental.autoingest; package org.sleuthkit.autopsy.guiutils;
import java.awt.Color;
import java.awt.Component; import java.awt.Component;
import java.time.Duration; import java.time.Duration;
import javax.swing.JTable; import javax.swing.JTable;
@ -28,11 +29,11 @@ import static javax.swing.SwingConstants.CENTER;
* string with days, hours, minutes, and seconds components. It center-aligns * string with days, hours, minutes, and seconds components. It center-aligns
* cell content and grays out the cell if the table is disabled. * cell content and grays out the cell if the table is disabled.
*/ */
class DurationCellRenderer extends GrayableCellRenderer { public class DurationCellRenderer extends GrayableCellRenderer {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
DurationCellRenderer() { public DurationCellRenderer() {
setHorizontalAlignment(CENTER); setHorizontalAlignment(CENTER);
} }
@ -71,4 +72,5 @@ class DurationCellRenderer extends GrayableCellRenderer {
grayCellIfTableNotEnabled(table, isSelected); grayCellIfTableNotEnabled(table, isSelected);
return this; return this;
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2015 Basis Technology Corp. * Copyright 2015-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.experimental.autoingest; package org.sleuthkit.autopsy.guiutils;
import java.awt.Color; import java.awt.Color;
import java.awt.Component; import java.awt.Component;
@ -28,11 +28,11 @@ import javax.swing.table.DefaultTableCellRenderer;
* A JTable cell renderer that left-aligns cell content and grays out the cell * A JTable cell renderer that left-aligns cell content and grays out the cell
* if the table is disabled. * if the table is disabled.
*/ */
class GrayableCellRenderer extends DefaultTableCellRenderer { public class GrayableCellRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
GrayableCellRenderer() { public GrayableCellRenderer() {
setHorizontalAlignment(LEFT); setHorizontalAlignment(LEFT);
} }
@ -45,7 +45,7 @@ class GrayableCellRenderer extends DefaultTableCellRenderer {
return this; return this;
} }
void grayCellIfTableNotEnabled(JTable table, boolean isSelected) { public void grayCellIfTableNotEnabled(JTable table, boolean isSelected) {
if (table.isEnabled()) { if (table.isEnabled()) {
/* /*
* The table is enabled, make the foreground and background the * The table is enabled, make the foreground and background the

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2015 Basis Technology Corp. * Copyright 2015-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.experimental.autoingest; package org.sleuthkit.autopsy.guiutils;
import java.awt.Component; import java.awt.Component;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
@ -28,7 +28,7 @@ import static javax.swing.SwingConstants.CENTER;
* center-aligned, long-format date string. It also grays out the cell if the * center-aligned, long-format date string. It also grays out the cell if the
* table is disabled. * table is disabled.
*/ */
class LongDateCellRenderer extends GrayableCellRenderer { public class LongDateCellRenderer extends GrayableCellRenderer {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final String FORMAT_STRING = "yyyy/MM/dd HH:mm:ss"; //NON-NLS private static final String FORMAT_STRING = "yyyy/MM/dd HH:mm:ss"; //NON-NLS

View File

@ -16,8 +16,9 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.experimental.autoingest; package org.sleuthkit.autopsy.guiutils;
import java.awt.Color;
import java.awt.Component; import java.awt.Component;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import javax.swing.JTable; import javax.swing.JTable;
@ -46,4 +47,5 @@ class ShortDateCellRenderer extends GrayableCellRenderer {
grayCellIfTableNotEnabled(table, isSelected); grayCellIfTableNotEnabled(table, isSelected);
return this; return this;
} }
} }

View File

@ -0,0 +1,74 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015-2017 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.guiutils;
import java.awt.Component;
import javax.swing.ImageIcon;
import javax.swing.JTable;
import static javax.swing.SwingConstants.CENTER;
import org.openide.util.ImageUtilities;
import org.openide.util.NbBundle.Messages;
/**
* A JTable cell renderer that represents a status as a center-aligned icon, and
* grays out the cell if the table is disabled. The statuses represented are OK,
* WARNING, and ERROR.
*/
public class StatusIconCellRenderer extends GrayableCellRenderer {
private static final long serialVersionUID = 1L;
static final ImageIcon OK_ICON = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/images/tick.png", false));
static final ImageIcon WARNING_ICON = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/images/warning16.png", false));
static final ImageIcon ERROR_ICON = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/images/cross-script.png", false));
@Messages({
"StatusIconCellRenderer.tooltiptext.ok=OK",
"StatusIconCellRenderer.tooltiptext.warning=A warning occurred",
"StatusIconCellRenderer.tooltiptext.error=An error occurred"
})
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
setHorizontalAlignment(CENTER);
if ((value instanceof Status)) {
switch((Status) value) {
case OK:
setIcon(OK_ICON);
setToolTipText(org.openide.util.NbBundle.getMessage(StatusIconCellRenderer.class, "StatusIconCellRenderer.tooltiptext.ok"));
break;
case WARNING:
setIcon(WARNING_ICON);
setToolTipText(org.openide.util.NbBundle.getMessage(StatusIconCellRenderer.class, "StatusIconCellRenderer.tooltiptext.warning"));
break;
case ERROR:
setIcon(ERROR_ICON);
setToolTipText(org.openide.util.NbBundle.getMessage(StatusIconCellRenderer.class, "StatusIconCellRenderer.tooltiptext.error"));
break;
}
}
grayCellIfTableNotEnabled(table, isSelected);
return this;
}
public enum Status {
OK,
WARNING,
ERROR
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 582 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 B

View File

@ -140,9 +140,35 @@ public class IngestOptionsPanel extends IngestModuleGlobalSettingsPanel implemen
@Override @Override
public void addPropertyChangeListener(PropertyChangeListener l) { public void addPropertyChangeListener(PropertyChangeListener l) {
filterPanel.addPropertyChangeListener(l); super.addPropertyChangeListener(l);
settingsPanel.addPropertyChangeListener(l); /*
profilePanel.addPropertyChangeListener(l); * There is at least one look and feel library that follows the bad
* practice of calling overrideable methods in a constructor, e.g.:
*
* at
* javax.swing.plaf.synth.SynthPanelUI.installListeners(SynthPanelUI.java:83)
* at
* javax.swing.plaf.synth.SynthPanelUI.installUI(SynthPanelUI.java:63)
* at javax.swing.JComponent.setUI(JComponent.java:666) at
* javax.swing.JPanel.setUI(JPanel.java:153) at
* javax.swing.JPanel.updateUI(JPanel.java:126) at
* javax.swing.JPanel.<init>(JPanel.java:86) at
* javax.swing.JPanel.<init>(JPanel.java:109) at
* javax.swing.JPanel.<init>(JPanel.java:117)
*
* When this happens, the following child components of this JPanel
* subclass have not been constructed yet, since this panel's
* constructor has not been called yet.
*/
if (null != filterPanel) {
filterPanel.addPropertyChangeListener(l);
}
if (null != settingsPanel) {
settingsPanel.addPropertyChangeListener(l);
}
if (null != profilePanel) {
profilePanel.addPropertyChangeListener(l);
}
} }
@Override @Override

View File

@ -177,7 +177,29 @@ class ProfilePanel extends IngestModuleGlobalSettingsPanel {
@Override @Override
public void addPropertyChangeListener(PropertyChangeListener l) { public void addPropertyChangeListener(PropertyChangeListener l) {
ingestSettingsPanel.addPropertyChangeListener(l); super.addPropertyChangeListener(l);
/*
* There is at least one look and feel library that follows the bad
* practice of calling overrideable methods in a constructor, e.g.:
*
* at
* javax.swing.plaf.synth.SynthPanelUI.installListeners(SynthPanelUI.java:83)
* at
* javax.swing.plaf.synth.SynthPanelUI.installUI(SynthPanelUI.java:63)
* at javax.swing.JComponent.setUI(JComponent.java:666) at
* javax.swing.JPanel.setUI(JPanel.java:153) at
* javax.swing.JPanel.updateUI(JPanel.java:126) at
* javax.swing.JPanel.<init>(JPanel.java:86) at
* javax.swing.JPanel.<init>(JPanel.java:109) at
* javax.swing.JPanel.<init>(JPanel.java:117)
*
* When this happens, the following child components of this JPanel
* subclass have not been constructed yet, since this panel's
* constructor has not been called yet.
*/
if (null != ingestSettingsPanel) {
ingestSettingsPanel.addPropertyChangeListener(l);
}
} }
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel jPanel1; private javax.swing.JPanel jPanel1;

View File

@ -1,6 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.4" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> <Form version="1.4" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[718, 430]"/>
</Property>
</Properties>
<AuxValues> <AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/> <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
@ -16,12 +21,12 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="jPanel1" alignment="0" pref="817" max="32767" attributes="0"/> <Component id="jPanel1" alignment="0" max="32767" attributes="0"/>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="jPanel1" alignment="0" pref="526" max="32767" attributes="0"/> <Component id="jPanel1" alignment="0" max="32767" attributes="0"/>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
</Layout> </Layout>
@ -29,7 +34,7 @@
<Container class="javax.swing.JPanel" name="jPanel1"> <Container class="javax.swing.JPanel" name="jPanel1">
<Properties> <Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[687, 450]"/> <Dimension value="[718, 430]"/>
</Property> </Property>
</Properties> </Properties>
@ -37,36 +42,45 @@
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="797" max="32767" attributes="0"/> <Component id="jScrollPane1" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="jScrollPane1" max="32767" attributes="0"/> <Component id="jScrollPane1" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
</Layout> </Layout>
<SubComponents> <SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane1"> <Container class="javax.swing.JScrollPane" name="jScrollPane1">
<Properties>
<Property name="requestFocusEnabled" type="boolean" value="false"/>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents> <SubComponents>
<Container class="javax.swing.JSplitPane" name="jSplitPane1"> <Container class="javax.swing.JSplitPane" name="jSplitPane1">
<Properties> <Properties>
<Property name="dividerLocation" type="int" value="430"/> <Property name="dividerLocation" type="int" value="365"/>
<Property name="dividerSize" type="int" value="1"/> <Property name="dividerSize" type="int" value="1"/>
</Properties> </Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/> <Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
<SubComponents> <SubComponents>
<Container class="javax.swing.JPanel" name="mimePanel"> <Container class="javax.swing.JPanel" name="mimePanel">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[369, 424]"/>
</Property>
<Property name="requestFocusEnabled" type="boolean" value="false"/>
</Properties>
<Constraints> <Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription"> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="left"/> <JSplitPaneConstraints position="left"/>
@ -76,23 +90,26 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane2" alignment="0" pref="0" max="32767" attributes="0"/> <Group type="102" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="286" max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel1" min="-2" max="-2" attributes="0"/> <Component id="jScrollPane2" min="-2" pref="349" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Component id="newTypeButton" min="-2" max="-2" attributes="0"/> <Component id="newTypeButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
<Component id="removeTypeButton" min="-2" max="-2" attributes="0"/> <Component id="removeTypeButton" min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
<EmptySpace min="0" pref="191" max="32767" attributes="0"/> <EmptySpace max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -101,14 +118,14 @@
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/> <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jScrollPane2" pref="427" max="32767" attributes="0"/> <Component id="jScrollPane2" pref="348" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
<Component id="newTypeButton" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="newTypeButton" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="removeTypeButton" alignment="3" min="-2" pref="25" max="-2" attributes="0"/> <Component id="removeTypeButton" alignment="3" min="-2" pref="25" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -142,6 +159,15 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.newTypeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.newTypeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newTypeButtonActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newTypeButtonActionPerformed"/>
@ -166,6 +192,11 @@
</SubComponents> </SubComponents>
</Container> </Container>
<Container class="javax.swing.JPanel" name="extensionPanel"> <Container class="javax.swing.JPanel" name="extensionPanel">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[344, 424]"/>
</Property>
</Properties>
<Constraints> <Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription"> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="right"/> <JSplitPaneConstraints position="right"/>
@ -198,16 +229,16 @@
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="extHeaderLabel" min="-2" max="-2" attributes="0"/> <Component id="extHeaderLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jScrollPane3" pref="427" max="32767" attributes="0"/> <Component id="jScrollPane3" pref="348" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
<Component id="newExtButton" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="newExtButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="removeExtButton" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="removeExtButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -221,6 +252,12 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.newExtButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.newExtButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newExtButtonActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newExtButtonActionPerformed"/>

View File

@ -154,11 +154,18 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
removeExtButton = new javax.swing.JButton(); removeExtButton = new javax.swing.JButton();
extHeaderLabel = new javax.swing.JLabel(); extHeaderLabel = new javax.swing.JLabel();
jPanel1.setPreferredSize(new java.awt.Dimension(687, 450)); setPreferredSize(new java.awt.Dimension(718, 430));
jSplitPane1.setDividerLocation(430); jPanel1.setPreferredSize(new java.awt.Dimension(718, 430));
jScrollPane1.setRequestFocusEnabled(false);
jSplitPane1.setDividerLocation(365);
jSplitPane1.setDividerSize(1); jSplitPane1.setDividerSize(1);
mimePanel.setPreferredSize(new java.awt.Dimension(369, 424));
mimePanel.setRequestFocusEnabled(false);
jLabel1.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.jLabel1.text")); // NOI18N jLabel1.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.jLabel1.text")); // NOI18N
mimeTable.setModel(mimeTableModel); mimeTable.setModel(mimeTableModel);
@ -166,6 +173,9 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
newTypeButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add16.png"))); // NOI18N newTypeButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add16.png"))); // NOI18N
newTypeButton.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.newTypeButton.text")); // NOI18N newTypeButton.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.newTypeButton.text")); // NOI18N
newTypeButton.setMaximumSize(new java.awt.Dimension(111, 25));
newTypeButton.setMinimumSize(new java.awt.Dimension(111, 25));
newTypeButton.setPreferredSize(new java.awt.Dimension(111, 25));
newTypeButton.addActionListener(new java.awt.event.ActionListener() { newTypeButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
newTypeButtonActionPerformed(evt); newTypeButtonActionPerformed(evt);
@ -188,16 +198,18 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
.addGroup(mimePanelLayout.createSequentialGroup() .addGroup(mimePanelLayout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(mimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(mimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) .addGroup(mimePanelLayout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(jLabel1)
.addGap(286, 286, 286))
.addGroup(mimePanelLayout.createSequentialGroup() .addGroup(mimePanelLayout.createSequentialGroup()
.addGroup(mimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(mimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel1) .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 349, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(mimePanelLayout.createSequentialGroup() .addGroup(mimePanelLayout.createSequentialGroup()
.addComponent(newTypeButton) .addComponent(newTypeButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGap(10, 10, 10)
.addComponent(removeTypeButton))) .addComponent(removeTypeButton)))
.addGap(0, 191, Short.MAX_VALUE))) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
.addContainerGap())
); );
mimePanelLayout.setVerticalGroup( mimePanelLayout.setVerticalGroup(
mimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) mimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -205,18 +217,22 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
.addContainerGap() .addContainerGap()
.addComponent(jLabel1) .addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 427, Short.MAX_VALUE) .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 348, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(mimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(mimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(newTypeButton) .addComponent(newTypeButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(removeTypeButton, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(removeTypeButton, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap()) .addContainerGap())
); );
jSplitPane1.setLeftComponent(mimePanel); jSplitPane1.setLeftComponent(mimePanel);
extensionPanel.setPreferredSize(new java.awt.Dimension(344, 424));
newExtButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add16.png"))); // NOI18N newExtButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add16.png"))); // NOI18N
newExtButton.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.newExtButton.text")); // NOI18N newExtButton.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.newExtButton.text")); // NOI18N
newExtButton.setMaximumSize(new java.awt.Dimension(111, 25));
newExtButton.setMinimumSize(new java.awt.Dimension(111, 25));
newExtButton.addActionListener(new java.awt.event.ActionListener() { newExtButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
newExtButtonActionPerformed(evt); newExtButtonActionPerformed(evt);
@ -248,7 +264,7 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
.addGroup(extensionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(extensionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(extHeaderLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 324, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(extHeaderLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 324, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(extensionPanelLayout.createSequentialGroup() .addGroup(extensionPanelLayout.createSequentialGroup()
.addComponent(newExtButton) .addComponent(newExtButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(removeExtButton))) .addComponent(removeExtButton)))
.addGap(0, 0, Short.MAX_VALUE))) .addGap(0, 0, Short.MAX_VALUE)))
@ -260,10 +276,10 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
.addContainerGap() .addContainerGap()
.addComponent(extHeaderLabel) .addComponent(extHeaderLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 427, Short.MAX_VALUE) .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 348, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(extensionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(extensionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(newExtButton) .addComponent(newExtButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(removeExtButton)) .addComponent(removeExtButton))
.addContainerGap()) .addContainerGap())
); );
@ -277,27 +293,27 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
jPanel1Layout.setHorizontalGroup( jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap() .addGap(0, 0, 0)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 797, Short.MAX_VALUE) .addComponent(jScrollPane1)
.addContainerGap()) .addGap(0, 0, 0))
); );
jPanel1Layout.setVerticalGroup( jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap() .addGap(0, 0, 0)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 504, Short.MAX_VALUE) .addComponent(jScrollPane1)
.addContainerGap()) .addGap(0, 0, 0))
); );
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 817, Short.MAX_VALUE) .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 526, Short.MAX_VALUE) .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents

View File

@ -32,10 +32,10 @@ import org.openide.util.Utilities;
import org.openide.util.actions.Presenter; import org.openide.util.actions.Presenter;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestManager;
import static org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.HashUtility; import org.sleuthkit.datamodel.HashUtility;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import static org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase;
/** /**
* Instances of this Action allow users to content to a hash database. * Instances of this Action allow users to content to a hash database.
@ -106,10 +106,10 @@ final class AddContentToHashDbAction extends AbstractAction implements Presenter
// Get the current set of updateable hash databases and add each // Get the current set of updateable hash databases and add each
// one to the menu as a separate menu item. Selecting a hash database // one to the menu as a separate menu item. Selecting a hash database
// adds the selected files to the selected database. // adds the selected files to the selected database.
final List<HashDatabase> hashDatabases = HashDbManager.getInstance().getUpdateableHashDatabases(); final List<HashDb> hashDatabases = HashDbManager.getInstance().getUpdateableHashSets();
if (!hashDatabases.isEmpty()) { if (!hashDatabases.isEmpty()) {
for (final HashDatabase database : hashDatabases) { for (final HashDb database : hashDatabases) {
JMenuItem databaseItem = add(database.getDisplayName()); JMenuItem databaseItem = add(database.getHashSetName());
databaseItem.addActionListener(new ActionListener() { databaseItem.addActionListener(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
@ -134,7 +134,7 @@ final class AddContentToHashDbAction extends AbstractAction implements Presenter
newHashSetItem.addActionListener(new ActionListener() { newHashSetItem.addActionListener(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
HashDatabase hashDb = new HashDbCreateDatabaseDialog().getHashDatabase(); HashDb hashDb = new HashDbCreateDatabaseDialog().getHashDatabase();
if (null != hashDb) { if (null != hashDb) {
addFilesToHashSet(selectedFiles, hashDb); addFilesToHashSet(selectedFiles, hashDb);
} }
@ -143,7 +143,7 @@ final class AddContentToHashDbAction extends AbstractAction implements Presenter
add(newHashSetItem); add(newHashSetItem);
} }
private void addFilesToHashSet(final Collection<? extends AbstractFile> files, HashDatabase hashSet) { private void addFilesToHashSet(final Collection<? extends AbstractFile> files, HashDb hashSet) {
for (AbstractFile file : files) { for (AbstractFile file : files) {
String md5Hash = file.getMd5Hash(); String md5Hash = file.getMd5Hash();
if (null != md5Hash) { if (null != md5Hash) {

View File

@ -31,8 +31,8 @@ import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.windows.WindowManager; import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.datamodel.HashEntry; import org.sleuthkit.datamodel.HashEntry;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase;
/** /**
* *
@ -40,7 +40,7 @@ import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase;
*/ */
public class AddHashValuesToDatabaseDialog extends javax.swing.JDialog { public class AddHashValuesToDatabaseDialog extends javax.swing.JDialog {
HashDatabase hashDb; HashDb hashDb;
Pattern md5Pattern = Pattern.compile("^[a-fA-F0-9]{32}$"); Pattern md5Pattern = Pattern.compile("^[a-fA-F0-9]{32}$");
List<HashEntry> hashes = new ArrayList<>(); List<HashEntry> hashes = new ArrayList<>();
List<String> invalidHashes = new ArrayList<>(); List<String> invalidHashes = new ArrayList<>();
@ -49,7 +49,7 @@ public class AddHashValuesToDatabaseDialog extends javax.swing.JDialog {
* Displays a dialog that allows a user to add hash values to the selected * Displays a dialog that allows a user to add hash values to the selected
* database. * database.
*/ */
AddHashValuesToDatabaseDialog(HashDatabase hashDb) { AddHashValuesToDatabaseDialog(HashDb hashDb) {
super((JFrame) WindowManager.getDefault().getMainWindow(), super((JFrame) WindowManager.getDefault().getMainWindow(),
NbBundle.getMessage(AddHashValuesToDatabaseDialog.class, "AddHashValuesToDatabaseDialog.JDialog.Title", hashDb.getDisplayName()), NbBundle.getMessage(AddHashValuesToDatabaseDialog.class, "AddHashValuesToDatabaseDialog.JDialog.Title", hashDb.getDisplayName()),
true); true);

View File

@ -31,9 +31,9 @@ import javax.swing.JScrollPane;
import javax.swing.JTextArea; import javax.swing.JTextArea;
import javax.swing.SwingWorker; import javax.swing.SwingWorker;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.datamodel.HashEntry; import org.sleuthkit.datamodel.HashEntry;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase;
/** /**
* *
@ -43,7 +43,7 @@ public class AddHashValuesToDatabaseProgressDialog extends javax.swing.JDialog {
private final AddHashValuesToDatabaseDialog parentRef; private final AddHashValuesToDatabaseDialog parentRef;
private boolean disposeParent = false; private boolean disposeParent = false;
private final HashDatabase hashDb; private final HashDb hashDb;
private final List<HashEntry> hashes; private final List<HashEntry> hashes;
private final List<String> invalidHashes; private final List<String> invalidHashes;
private final Pattern md5Pattern; private final Pattern md5Pattern;
@ -58,7 +58,7 @@ public class AddHashValuesToDatabaseProgressDialog extends javax.swing.JDialog {
* @param hashDb * @param hashDb
* @param text * @param text
*/ */
AddHashValuesToDatabaseProgressDialog(AddHashValuesToDatabaseDialog parent, HashDatabase hashDb, String text) { AddHashValuesToDatabaseProgressDialog(AddHashValuesToDatabaseDialog parent, HashDb hashDb, String text) {
super(parent); super(parent);
initComponents(); initComponents();
display(); display();

View File

@ -34,13 +34,14 @@ import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization; import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamGlobalSet;
import org.sleuthkit.autopsy.centralrepository.optionspanel.ManageOrganizationsDialog; import org.sleuthkit.autopsy.centralrepository.optionspanel.ManageOrganizationsDialog;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDbManagerException; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDbManagerException;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase;
import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
@ -54,7 +55,7 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog {
private static final String DEFAULT_FILE_NAME = NbBundle private static final String DEFAULT_FILE_NAME = NbBundle
.getMessage(HashDbCreateDatabaseDialog.class, "HashDbCreateDatabaseDialog.defaultFileName"); .getMessage(HashDbCreateDatabaseDialog.class, "HashDbCreateDatabaseDialog.defaultFileName");
private JFileChooser fileChooser = null; private JFileChooser fileChooser = null;
private HashDatabase newHashDb = null; private HashDb newHashDb = null;
private final static String LAST_FILE_PATH_KEY = "HashDbCreate_Path"; private final static String LAST_FILE_PATH_KEY = "HashDbCreate_Path";
private EamOrganization selectedOrg = null; private EamOrganization selectedOrg = null;
private List<EamOrganization> orgs = null; private List<EamOrganization> orgs = null;
@ -77,7 +78,7 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog {
* *
* @return A HashDb object or null. * @return A HashDb object or null.
*/ */
HashDatabase getHashDatabase() { HashDb getHashDatabase() {
return newHashDb; return newHashDb;
} }
@ -474,9 +475,10 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog {
String errorMessage = NbBundle String errorMessage = NbBundle
.getMessage(this.getClass(), "HashDbCreateDatabaseDialog.errMsg.hashDbCreationErr"); .getMessage(this.getClass(), "HashDbCreateDatabaseDialog.errMsg.hashDbCreationErr");
if(fileTypeRadioButton.isSelected()){ if(fileTypeRadioButton.isSelected()){
try { try {
newHashDb = HashDbManager.getInstance().addNewFileTypeHashDatabase(hashSetNameTextField.getText(), fileChooser.getSelectedFile().getCanonicalPath(), true, sendIngestMessagesCheckbox.isSelected(), type); newHashDb = HashDbManager.getInstance().addNewHashDatabaseNoSave(hashSetNameTextField.getText(), fileChooser.getSelectedFile().getCanonicalPath(), true, sendIngestMessagesCheckbox.isSelected(), type);
} catch (IOException ex) { } catch (IOException ex) {
Logger.getLogger(HashDbCreateDatabaseDialog.class.getName()).log(Level.WARNING, errorMessage, ex); Logger.getLogger(HashDbCreateDatabaseDialog.class.getName()).log(Level.WARNING, errorMessage, ex);
JOptionPane.showMessageDialog(this, JOptionPane.showMessageDialog(this,
@ -519,10 +521,10 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog {
} }
try{ try{
int crIndex = EamDb.getInstance().newReferenceSet(selectedOrg.getOrgID(), hashSetNameTextField.getText(), int referenceSetID = EamDb.getInstance().newReferenceSet(new EamGlobalSet(selectedOrg.getOrgID(), hashSetNameTextField.getText(),
EamDb.getDefaultVersion(), fileKnown, false); EamDb.getDefaultVersion(), fileKnown, false));
newHashDb = HashDbManager.getInstance().addExistingCentralRepoHashSet(hashSetNameTextField.getText(), newHashDb = HashDbManager.getInstance().addExistingCentralRepoHashSet(hashSetNameTextField.getText(),
EamDb.getDefaultVersion(), crIndex, EamDb.getDefaultVersion(), referenceSetID,
true, sendIngestMessagesCheckbox.isSelected(), type, false); true, sendIngestMessagesCheckbox.isSelected(), type, false);
} catch (EamDbException | TskCoreException ex){ } catch (EamDbException | TskCoreException ex){
Logger.getLogger(HashDbImportDatabaseDialog.class.getName()).log(Level.SEVERE, "Error creating new reference set", ex); Logger.getLogger(HashDbImportDatabaseDialog.class.getName()).log(Level.SEVERE, "Error creating new reference set", ex);

View File

@ -41,7 +41,7 @@ import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDbManagerException; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDbManagerException;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
/** /**
* Instances of this class allow a user to select an existing hash database and * Instances of this class allow a user to select an existing hash database and
@ -52,7 +52,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog {
private JFileChooser fileChooser = new JFileChooser(); private JFileChooser fileChooser = new JFileChooser();
private String selectedFilePath = ""; private String selectedFilePath = "";
private HashDatabase selectedHashDb = null; private HashDb selectedHashDb = null;
private final static String LAST_FILE_PATH_KEY = "HashDbImport_Path"; private final static String LAST_FILE_PATH_KEY = "HashDbImport_Path";
private EamOrganization selectedOrg = null; private EamOrganization selectedOrg = null;
private List<EamOrganization> orgs = null; private List<EamOrganization> orgs = null;
@ -77,7 +77,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog {
* *
* @return A HashDb object or null. * @return A HashDb object or null.
*/ */
HashDatabase getHashDatabase() { HashDb getHashDatabase() {
return selectedHashDb; return selectedHashDb;
} }
@ -518,7 +518,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog {
if(fileTypeRadioButton.isSelected()){ if(fileTypeRadioButton.isSelected()){
try { try {
selectedHashDb = HashDbManager.getInstance().addExistingFileTypeHashDatabase(hashSetNameTextField.getText(), selectedFilePath, true, sendIngestMessagesCheckbox.isSelected(), type); selectedHashDb = HashDbManager.getInstance().addExistingHashDatabaseNoSave(hashSetNameTextField.getText(), selectedFilePath, true, sendIngestMessagesCheckbox.isSelected(), type);
} catch (HashDbManagerException ex) { } catch (HashDbManagerException ex) {
Logger.getLogger(HashDbImportDatabaseDialog.class.getName()).log(Level.WARNING, errorMessage, ex); Logger.getLogger(HashDbImportDatabaseDialog.class.getName()).log(Level.WARNING, errorMessage, ex);
JOptionPane.showMessageDialog(this, JOptionPane.showMessageDialog(this,

View File

@ -36,7 +36,7 @@ import org.sleuthkit.autopsy.ingest.IngestMessage;
import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter; import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
@ -63,8 +63,8 @@ public class HashDbIngestModule implements FileIngestModule {
private final SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); private final SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase();
private final HashDbManager hashDbManager = HashDbManager.getInstance(); private final HashDbManager hashDbManager = HashDbManager.getInstance();
private final HashLookupModuleSettings settings; private final HashLookupModuleSettings settings;
private List<HashDatabase> knownBadHashSets = new ArrayList<>(); private List<HashDb> knownBadHashSets = new ArrayList<>();
private List<HashDatabase> knownHashSets = new ArrayList<>(); private List<HashDb> knownHashSets = new ArrayList<>();
private long jobId; private long jobId;
private static final HashMap<Long, IngestJobTotals> totalsForIngestJobs = new HashMap<>(); private static final HashMap<Long, IngestJobTotals> totalsForIngestJobs = new HashMap<>();
private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter(); private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter();
@ -96,8 +96,8 @@ public class HashDbIngestModule implements FileIngestModule {
if (!hashDbManager.verifyAllDatabasesLoadedCorrectly()) { if (!hashDbManager.verifyAllDatabasesLoadedCorrectly()) {
throw new IngestModuleException("Could not load all hash databases"); throw new IngestModuleException("Could not load all hash databases");
} }
updateEnabledHashSets(hashDbManager.getNotableFileHashDatabases(), knownBadHashSets); updateEnabledHashSets(hashDbManager.getKnownBadFileHashSets(), knownBadHashSets);
updateEnabledHashSets(hashDbManager.getKnownFileHashDatabases(), knownHashSets); updateEnabledHashSets(hashDbManager.getKnownFileHashSets(), knownHashSets);
if (refCounter.incrementAndGet(jobId) == 1) { if (refCounter.incrementAndGet(jobId) == 1) {
// initialize job totals // initialize job totals
@ -126,9 +126,9 @@ public class HashDbIngestModule implements FileIngestModule {
* @param allHashSets List of all hashsets from DB manager * @param allHashSets List of all hashsets from DB manager
* @param enabledHashSets List of enabled ones to return. * @param enabledHashSets List of enabled ones to return.
*/ */
private void updateEnabledHashSets(List<HashDatabase> allHashSets, List<HashDatabase> enabledHashSets) { private void updateEnabledHashSets(List<HashDb> allHashSets, List<HashDb> enabledHashSets) {
enabledHashSets.clear(); enabledHashSets.clear();
for (HashDatabase db : allHashSets) { for (HashDb db : allHashSets) {
if (settings.isHashSetEnabled(db)) { if (settings.isHashSetEnabled(db)) {
try { try {
if (db.isValid()) { if (db.isValid()) {
@ -196,7 +196,7 @@ public class HashDbIngestModule implements FileIngestModule {
// look up in notable first // look up in notable first
boolean foundBad = false; boolean foundBad = false;
ProcessResult ret = ProcessResult.OK; ProcessResult ret = ProcessResult.OK;
for (HashDatabase db : knownBadHashSets) { for (HashDb db : knownBadHashSets) {
try { try {
long lookupstart = System.currentTimeMillis(); long lookupstart = System.currentTimeMillis();
HashHitInfo hashInfo = db.lookupMD5(file); HashHitInfo hashInfo = db.lookupMD5(file);
@ -257,7 +257,7 @@ public class HashDbIngestModule implements FileIngestModule {
// Any hit is sufficient to classify it as known, and there is no need to create // Any hit is sufficient to classify it as known, and there is no need to create
// a hit artifact or send a message to the application inbox. // a hit artifact or send a message to the application inbox.
if (!foundBad) { if (!foundBad) {
for (HashDatabase db : knownHashSets) { for (HashDb db : knownHashSets) {
try { try {
long lookupstart = System.currentTimeMillis(); long lookupstart = System.currentTimeMillis();
if (db.lookupMD5Quick(file)) { if (db.lookupMD5Quick(file)) {
@ -359,7 +359,7 @@ public class HashDbIngestModule implements FileIngestModule {
} }
private static synchronized void postSummary(long jobId, private static synchronized void postSummary(long jobId,
List<HashDatabase> knownBadHashSets, List<HashDatabase> knownHashSets) { List<HashDb> knownBadHashSets, List<HashDb> knownHashSets) {
IngestJobTotals jobTotals = getTotalsForIngestJobs(jobId); IngestJobTotals jobTotals = getTotalsForIngestJobs(jobId);
totalsForIngestJobs.remove(jobId); totalsForIngestJobs.remove(jobId);
@ -384,8 +384,8 @@ public class HashDbIngestModule implements FileIngestModule {
detailsSb.append("<p>") //NON-NLS detailsSb.append("<p>") //NON-NLS
.append(NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.complete.databasesUsed")) .append(NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.complete.databasesUsed"))
.append("</p>\n<ul>"); //NON-NLS .append("</p>\n<ul>"); //NON-NLS
for (HashDatabase db : knownBadHashSets) { for (HashDb db : knownBadHashSets) {
detailsSb.append("<li>").append(db.getDisplayName()).append("</li>\n"); //NON-NLS detailsSb.append("<li>").append(db.getHashSetName()).append("</li>\n"); //NON-NLS
} }
detailsSb.append("</ul>"); //NON-NLS detailsSb.append("</ul>"); //NON-NLS

View File

@ -64,7 +64,7 @@ public class HashDbManager implements PropertyChangeListener {
private static final String HASH_DATABASE_FILE_EXTENSON = "kdb"; //NON-NLS private static final String HASH_DATABASE_FILE_EXTENSON = "kdb"; //NON-NLS
private static HashDbManager instance = null; private static HashDbManager instance = null;
private List<HashDatabase> hashSets = new ArrayList<>(); private List<HashDb> hashSets = new ArrayList<>();
private Set<String> hashSetNames = new HashSet<>(); private Set<String> hashSetNames = new HashSet<>();
private Set<String> hashSetPaths = new HashSet<>(); private Set<String> hashSetPaths = new HashSet<>();
PropertyChangeSupport changeSupport = new PropertyChangeSupport(HashDbManager.class); PropertyChangeSupport changeSupport = new PropertyChangeSupport(HashDbManager.class);
@ -150,7 +150,6 @@ public class HashDbManager implements PropertyChangeListener {
* *
* @throws HashDbManagerException * @throws HashDbManagerException
*/ */
@Deprecated
public synchronized HashDb addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException { public synchronized HashDb addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
HashDb hashDb = null; HashDb hashDb = null;
hashDb = this.addExistingHashDatabaseNoSave(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType); hashDb = this.addExistingHashDatabaseNoSave(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType);
@ -158,12 +157,7 @@ public class HashDbManager implements PropertyChangeListener {
return hashDb; return hashDb;
} }
@Deprecated
synchronized HashDb addExistingHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException { synchronized HashDb addExistingHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
return (HashDb)addExistingFileTypeHashDatabase(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType);
}
synchronized HashDatabase addExistingFileTypeHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
HashDb hashDb = null; HashDb hashDb = null;
try { try {
if (!new File(path).exists()) { if (!new File(path).exists()) {
@ -178,7 +172,7 @@ public class HashDbManager implements PropertyChangeListener {
throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.duplicateHashSetNameExceptionMsg", hashSetName)); throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.duplicateHashSetNameExceptionMsg", hashSetName));
} }
hashDb = addFileTypeHashDatabase(SleuthkitJNI.openHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType); hashDb = addHashDatabase(SleuthkitJNI.openHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
throw new HashDbManagerException(ex.getMessage()); throw new HashDbManagerException(ex.getMessage());
} }
@ -203,7 +197,6 @@ public class HashDbManager implements PropertyChangeListener {
* *
* @throws HashDbManagerException * @throws HashDbManagerException
*/ */
@Deprecated
public synchronized HashDb addNewHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, public synchronized HashDb addNewHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages,
HashDb.KnownFilesType knownFilesType) throws HashDbManagerException { HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
@ -215,14 +208,8 @@ public class HashDbManager implements PropertyChangeListener {
return hashDb; return hashDb;
} }
@Deprecated
public synchronized HashDb addNewHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, public synchronized HashDb addNewHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages,
HashDb.KnownFilesType knownFilesType) throws HashDbManagerException { HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
return (HashDb)addNewFileTypeHashDatabase(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType);
}
public synchronized HashDatabase addNewFileTypeHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages,
HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
HashDb hashDb = null; HashDb hashDb = null;
try { try {
File file = new File(path); File file = new File(path);
@ -242,16 +229,16 @@ public class HashDbManager implements PropertyChangeListener {
throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.duplicateHashSetNameExceptionMsg", hashSetName)); throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.duplicateHashSetNameExceptionMsg", hashSetName));
} }
hashDb = addFileTypeHashDatabase(SleuthkitJNI.createHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType); hashDb = addHashDatabase(SleuthkitJNI.createHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
throw new HashDbManagerException(ex.getMessage()); throw new HashDbManagerException(ex.getMessage());
} }
return hashDb; return hashDb;
} }
private HashDb addFileTypeHashDatabase(int handle, String hashSetName, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws TskCoreException { private SleuthkitHashSet addHashDatabase(int handle, String hashSetName, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws TskCoreException {
// Wrap an object around the handle. // Wrap an object around the handle.
HashDb hashDb = new HashDb(handle, hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType); SleuthkitHashSet hashDb = new SleuthkitHashSet(handle, hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
// Get the indentity data before updating the collections since the // Get the indentity data before updating the collections since the
// accessor methods may throw. // accessor methods may throw.
@ -284,7 +271,7 @@ public class HashDbManager implements PropertyChangeListener {
return hashDb; return hashDb;
} }
public CentralRepoHashDb addExistingCentralRepoHashSet(String hashSetName, String version, int referenceSetID, CentralRepoHashSet addExistingCentralRepoHashSet(String hashSetName, String version, int referenceSetID,
boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType,
boolean readOnly) throws TskCoreException{ boolean readOnly) throws TskCoreException{
@ -292,7 +279,7 @@ public class HashDbManager implements PropertyChangeListener {
throw new TskCoreException("Could not load central repository database " + hashSetName + " - central repository is not enabled"); throw new TskCoreException("Could not load central repository database " + hashSetName + " - central repository is not enabled");
} }
CentralRepoHashDb db = new CentralRepoHashDb(hashSetName, version, referenceSetID, searchDuringIngest, CentralRepoHashSet db = new CentralRepoHashSet(hashSetName, version, referenceSetID, searchDuringIngest,
sendIngestMessages, knownFilesType, readOnly); sendIngestMessages, knownFilesType, readOnly);
if(! db.isValid()){ if(! db.isValid()){
@ -316,7 +303,7 @@ public class HashDbManager implements PropertyChangeListener {
} }
synchronized void indexHashDatabase(HashDb hashDb) { synchronized void indexHashDatabase(SleuthkitHashSet hashDb) {
hashDb.addPropertyChangeListener(this); hashDb.addPropertyChangeListener(this);
HashDbIndexer creator = new HashDbIndexer(hashDb); HashDbIndexer creator = new HashDbIndexer(hashDb);
creator.execute(); creator.execute();
@ -324,8 +311,8 @@ public class HashDbManager implements PropertyChangeListener {
@Override @Override
public void propertyChange(PropertyChangeEvent event) { public void propertyChange(PropertyChangeEvent event) {
if (event.getPropertyName().equals(HashDb.Event.INDEXING_DONE.name())) { if (event.getPropertyName().equals(SleuthkitHashSet.Event.INDEXING_DONE.name())) {
HashDb hashDb = (HashDb) event.getNewValue(); SleuthkitHashSet hashDb = (SleuthkitHashSet) event.getNewValue();
if (null != hashDb) { if (null != hashDb) {
try { try {
String indexPath = hashDb.getIndexPath(); String indexPath = hashDb.getIndexPath();
@ -347,12 +334,12 @@ public class HashDbManager implements PropertyChangeListener {
* *
* @throws HashDbManagerException * @throws HashDbManagerException
*/ */
public synchronized void removeHashDatabase(HashDatabase hashDb) throws HashDbManagerException { public synchronized void removeHashDatabase(HashDb hashDb) throws HashDbManagerException {
this.removeHashDatabaseNoSave(hashDb); this.removeHashDatabaseNoSave(hashDb);
this.save(); this.save();
} }
public synchronized void removeHashDatabaseNoSave(HashDatabase hashDatabase) throws HashDbManagerException { public synchronized void removeHashDatabaseNoSave(HashDb hashDb) throws HashDbManagerException {
// Don't remove a database if ingest is running // Don't remove a database if ingest is running
boolean ingestIsRunning = IngestManager.getInstance().isIngestRunning(); boolean ingestIsRunning = IngestManager.getInstance().isIngestRunning();
if (ingestIsRunning) { if (ingestIsRunning) {
@ -362,36 +349,36 @@ public class HashDbManager implements PropertyChangeListener {
// and remove its hash set name from the hash set used to ensure unique // and remove its hash set name from the hash set used to ensure unique
// hash set names are used, before undertaking These operations will succeed and constitute // hash set names are used, before undertaking These operations will succeed and constitute
// a mostly effective removal, even if the subsequent operations fail. // a mostly effective removal, even if the subsequent operations fail.
String hashSetName = hashDatabase.getHashSetName(); String hashSetName = hashDb.getHashSetName();
hashSetNames.remove(hashSetName); hashSetNames.remove(hashSetName);
hashSets.remove(hashDatabase); hashSets.remove(hashDb);
// Now undertake the operations that could throw. // Now undertake the operations that could throw.
// Indexing is only relevanet for file type hashsets // Indexing is only relevanet for sleuthkit hashsets
if(hashDatabase instanceof HashDb){ if(hashDb instanceof SleuthkitHashSet){
HashDb hashDb = (HashDb)hashDatabase; SleuthkitHashSet hashDatabase = (SleuthkitHashSet)hashDb;
try { try {
if(hashDb.hasIndex()){ if(hashDatabase.hasIndex()){
hashSetPaths.remove(hashDb.getIndexPath()); hashSetPaths.remove(hashDatabase.getIndexPath());
} }
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error getting index path of " + hashDb.getHashSetName() + " hash database when removing the database", ex); //NON-NLS Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error getting index path of " + hashDatabase.getHashSetName() + " hash database when removing the database", ex); //NON-NLS
} }
try { try {
if (!hashDb.hasIndexOnly()) { if (!hashDatabase.hasIndexOnly()) {
hashSetPaths.remove(hashDb.getDatabasePath()); hashSetPaths.remove(hashDatabase.getDatabasePath());
} }
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error getting database path of " + hashDb.getHashSetName() + " hash database when removing the database", ex); //NON-NLS Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error getting database path of " + hashDatabase.getHashSetName() + " hash database when removing the database", ex); //NON-NLS
} }
}
try { try {
hashDatabase.close(); hashDatabase.close();
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error closing " + hashDatabase.getHashSetName() + " hash database when removing the database", ex); //NON-NLS Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error closing " + hashDb.getHashSetName() + " hash database when removing the database", ex); //NON-NLS
}
} }
// Let any external listeners know that a set has been deleted // Let any external listeners know that a set has been deleted
@ -418,66 +405,20 @@ public class HashDbManager implements PropertyChangeListener {
/** /**
* Gets all of the hash databases used to classify files as known or known * Gets all of the hash databases used to classify files as known or known
* bad. * bad. Will add any new central repository databases to the list before
* returning it.
* *
* @return A list, possibly empty, of hash databases. * @return A list, possibly empty, of hash databases.
*/ */
@Deprecated
public synchronized List<HashDb> getAllHashSets() { public synchronized List<HashDb> getAllHashSets() {
return getAllFileTypeHashSets();
}
/**
* Gets all of the file type hash databases used to classify files as known or known
* bad.
*
* @return A list, possibly empty, of hash databases.
*/
public synchronized List<HashDb> getAllFileTypeHashSets() {
List<HashDb> hashDbs = new ArrayList<>();
this.hashSets.stream().filter((thisSet) -> (thisSet instanceof HashDb)).forEach((thisSet) -> {
hashDbs.add((HashDb)thisSet);
});
return hashDbs;
}
/**
* Gets all of the hash databases used to classify files as known or known
* bad.
*
* @return A list, possibly empty, of hash databases.
*/
public synchronized List<HashDatabase> getAllHashDatabases(){
List<HashDatabase> hashDbs = new ArrayList<>();
hashDbs.addAll(this.hashSets);
return hashDbs;
}
/**
* Adds any new central repository databases to the list of hashes
* before returning a copy of the hash set list
* @return A list, possibly empty, of hash databases.
*/
public synchronized List<HashDatabase> refreshAndGetAllHashDatabases(){
try{ try{
updateHashSetsFromCentralRepository(); updateHashSetsFromCentralRepository();
} catch (TskCoreException ex){ } catch (TskCoreException ex){
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS
} }
return getAllHashDatabases();
}
/**
* Gets all of the hash databases used to classify files as known.
*
* @return A list, possibly empty, of hash databases.
*/
@Deprecated
public synchronized List<HashDb> getKnownFileHashSets() {
List<HashDb> hashDbs = new ArrayList<>(); List<HashDb> hashDbs = new ArrayList<>();
this.hashSets.stream().filter((thisSet) -> ((thisSet instanceof HashDb) && (thisSet.getKnownFilesType() == HashDb.KnownFilesType.KNOWN))).forEach((thisSet) -> { hashDbs.addAll(this.hashSets);
hashDbs.add((HashDb)thisSet);
});
return hashDbs; return hashDbs;
} }
@ -486,8 +427,13 @@ public class HashDbManager implements PropertyChangeListener {
* *
* @return A list, possibly empty, of hash databases. * @return A list, possibly empty, of hash databases.
*/ */
public synchronized List<HashDatabase> getKnownFileHashDatabases() { public synchronized List<HashDb> getKnownFileHashSets() {
List<HashDatabase> hashDbs = new ArrayList<>(); List<HashDb> hashDbs = new ArrayList<>();
try{
updateHashSetsFromCentralRepository();
} catch (TskCoreException ex){
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS
}
this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == HashDb.KnownFilesType.KNOWN)).forEach((db) -> { this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == HashDb.KnownFilesType.KNOWN)).forEach((db) -> {
hashDbs.add(db); hashDbs.add(db);
}); });
@ -499,22 +445,13 @@ public class HashDbManager implements PropertyChangeListener {
* *
* @return A list, possibly empty, of hash databases. * @return A list, possibly empty, of hash databases.
*/ */
@Deprecated
public synchronized List<HashDb> getKnownBadFileHashSets() { public synchronized List<HashDb> getKnownBadFileHashSets() {
List<HashDb> hashDbs = new ArrayList<>(); List<HashDb> hashDbs = new ArrayList<>();
this.hashSets.stream().filter((thisSet) -> ((thisSet instanceof HashDb) && (thisSet.getKnownFilesType() == HashDb.KnownFilesType.KNOWN_BAD))).forEach((thisSet) -> { try{
hashDbs.add((HashDb)thisSet); updateHashSetsFromCentralRepository();
}); } catch (TskCoreException ex){
return hashDbs; Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS
} }
/**
* Gets all of the hash databases used to classify files as notable.
*
* @return A list, possibly empty, of hash databases.
*/
public synchronized List<HashDatabase> getNotableFileHashDatabases() {
List<HashDatabase> hashDbs = new ArrayList<>();
this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == HashDb.KnownFilesType.KNOWN_BAD)).forEach((db) -> { this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == HashDb.KnownFilesType.KNOWN_BAD)).forEach((db) -> {
hashDbs.add(db); hashDbs.add(db);
}); });
@ -526,28 +463,18 @@ public class HashDbManager implements PropertyChangeListener {
* *
* @return A list, possibly empty, of hash databases. * @return A list, possibly empty, of hash databases.
*/ */
@Deprecated
public synchronized List<HashDb> getUpdateableHashSets() { public synchronized List<HashDb> getUpdateableHashSets() {
List<HashDb> updateableDbs = new ArrayList<>();
List<HashDatabase> updateableHashSets = getUpdateableHashSets(this.hashSets);
updateableHashSets.stream().filter((db) -> (db instanceof HashDb)).forEach((db) -> {
updateableDbs.add((HashDb)db);
});
return updateableDbs;
}
/**
* Gets all of the hash databases that accept updates.
*
* @return A list, possibly empty, of hash databases.
*/
public synchronized List<HashDatabase> getUpdateableHashDatabases(){
return getUpdateableHashSets(this.hashSets); return getUpdateableHashSets(this.hashSets);
} }
private List<HashDatabase> getUpdateableHashSets(List<HashDatabase> hashDbs) { private List<HashDb> getUpdateableHashSets(List<HashDb> hashDbs) {
ArrayList<HashDatabase> updateableDbs = new ArrayList<>(); ArrayList<HashDb> updateableDbs = new ArrayList<>();
for (HashDatabase db : hashDbs) { try{
updateHashSetsFromCentralRepository();
} catch (TskCoreException ex){
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS
}
for (HashDb db : hashDbs) {
try { try {
if (db.isUpdateable()) { if (db.isUpdateable()) {
updateableDbs.add(db); updateableDbs.add(db);
@ -569,9 +496,9 @@ public class HashDbManager implements PropertyChangeListener {
// Defaults for fields not stored in the central repository: // Defaults for fields not stored in the central repository:
// searchDuringIngest: false // searchDuringIngest: false
// sendIngestMessages: true if the hash set is notable // sendIngestMessages: true if the hash set is notable
boolean sendIngestMessages = globalSet.getKnownStatus().equals(HashDb.KnownFilesType.KNOWN_BAD); boolean sendIngestMessages = convertFileKnown(globalSet.getFileKnownStatus()).equals(HashDb.KnownFilesType.KNOWN_BAD);
crHashSets.add(new HashDbInfo(globalSet.getSetName(), globalSet.getVersion(), crHashSets.add(new HashDbInfo(globalSet.getSetName(), globalSet.getVersion(),
globalSet.getGlobalSetID(), globalSet.getKnownStatus(), globalSet.isReadOnly(), false, sendIngestMessages)); globalSet.getGlobalSetID(), convertFileKnown(globalSet.getFileKnownStatus()), globalSet.isReadOnly(), false, sendIngestMessages));
} }
} catch (EamDbException ex){ } catch (EamDbException ex){
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS
@ -580,6 +507,13 @@ public class HashDbManager implements PropertyChangeListener {
return crHashSets; return crHashSets;
} }
private static HashDb.KnownFilesType convertFileKnown(TskData.FileKnown fileKnown){
if(fileKnown.equals(TskData.FileKnown.BAD)){
return HashDb.KnownFilesType.KNOWN_BAD;
}
return HashDb.KnownFilesType.KNOWN;
}
/** /**
* Restores the last saved hash sets configuration. This supports * Restores the last saved hash sets configuration. This supports
* cancellation of configuration panels. * cancellation of configuration panels.
@ -592,12 +526,14 @@ public class HashDbManager implements PropertyChangeListener {
loadHashsetsConfiguration(); loadHashsetsConfiguration();
} }
private void closeHashDatabases(List<HashDatabase> hashDatabases) { private void closeHashDatabases(List<HashDb> hashDatabases) {
for (HashDatabase database : hashDatabases) { for (HashDb database : hashDatabases) {
try { if(database instanceof SleuthkitHashSet){
database.close(); try {
} catch (TskCoreException ex) { ((SleuthkitHashSet)database).close();
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error closing " + database.getHashSetName() + " hash database", ex); //NON-NLS } catch (TskCoreException ex) {
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error closing " + database.getHashSetName() + " hash database", ex); //NON-NLS
}
} }
} }
hashDatabases.clear(); hashDatabases.clear();
@ -628,7 +564,7 @@ public class HashDbManager implements PropertyChangeListener {
if(hashDbInfo.isFileDatabaseType()){ if(hashDbInfo.isFileDatabaseType()){
String dbPath = this.getValidFilePath(hashDbInfo.getHashSetName(), hashDbInfo.getPath()); String dbPath = this.getValidFilePath(hashDbInfo.getHashSetName(), hashDbInfo.getPath());
if (dbPath != null) { if (dbPath != null) {
addFileTypeHashDatabase(SleuthkitJNI.openHashDatabase(dbPath), hashDbInfo.getHashSetName(), hashDbInfo.getSearchDuringIngest(), hashDbInfo.getSendIngestMessages(), hashDbInfo.getKnownFilesType()); addHashDatabase(SleuthkitJNI.openHashDatabase(dbPath), hashDbInfo.getHashSetName(), hashDbInfo.getSearchDuringIngest(), hashDbInfo.getSendIngestMessages(), hashDbInfo.getKnownFilesType());
} else { } else {
logger.log(Level.WARNING, Bundle.HashDbManager_noDbPath_message(hashDbInfo.getHashSetName())); logger.log(Level.WARNING, Bundle.HashDbManager_noDbPath_message(hashDbInfo.getHashSetName()));
allDatabasesLoadedCorrectly = false; allDatabasesLoadedCorrectly = false;
@ -684,7 +620,7 @@ public class HashDbManager implements PropertyChangeListener {
} }
} }
void updateHashSetsFromCentralRepository() throws TskCoreException { private void updateHashSetsFromCentralRepository() throws TskCoreException {
if(EamDb.isEnabled()){ if(EamDb.isEnabled()){
List<HashDbInfo> crHashDbInfoList = getCentralRepoHashSetsFromDatabase(); List<HashDbInfo> crHashDbInfoList = getCentralRepoHashSetsFromDatabase();
for(HashDbInfo hashDbInfo : crHashDbInfoList) { for(HashDbInfo hashDbInfo : crHashDbInfoList) {
@ -699,7 +635,7 @@ public class HashDbManager implements PropertyChangeListener {
} }
private boolean hashDbInfoIsNew(HashDbInfo dbInfo){ private boolean hashDbInfoIsNew(HashDbInfo dbInfo){
for(HashDatabase db:this.hashSets){ for(HashDb db:this.hashSets){
if(dbInfo.matches(db)){ if(dbInfo.matches(db)){
return false; return false;
} }
@ -754,88 +690,7 @@ public class HashDbManager implements PropertyChangeListener {
return filePath; return filePath;
} }
public static interface HashDatabase { public static abstract class HashDb {
enum DatabaseType{
FILE,
CENTRAL_REPOSITORY
};
public String getHashSetName();
public String getDisplayName();
public String getDatabasePath() throws TskCoreException;
public HashDb.KnownFilesType getKnownFilesType();
public boolean getSearchDuringIngest();
public boolean getDefaultSearchDuringIngest();
void setSearchDuringIngest(boolean useForIngest);
public boolean getSendIngestMessages();
void setSendIngestMessages(boolean showInboxMessages);
/**
* Indicates whether the hash database accepts updates.
*
* @return True if the database accepts updates, false otherwise.
*
* @throws org.sleuthkit.datamodel.TskCoreException
*/
public boolean isUpdateable() throws TskCoreException;
/**
* Adds hashes of content (if calculated) to the hash database.
*
* @param content The content for which the calculated hashes, if any,
* are to be added to the hash database.
*
* @throws TskCoreException
*/
public void addHashes(Content content) throws TskCoreException;
public void addHashes(Content content, String comment) throws TskCoreException;
public void addHashes(List<HashEntry> hashes) throws TskCoreException;
public boolean lookupMD5Quick(Content content) throws TskCoreException;
public HashHitInfo lookupMD5(Content content) throws TskCoreException;
/**
* Returns whether this database can be enabled.
* For file type, this is the same as checking that it has an index
* @return true if is valid, false otherwise
* @throws TskCoreException
*/
public boolean isValid() throws TskCoreException;
public int getHandle();
public void firePropertyChange(String propertyName, Object oldValue, Object newValue);
public void addPropertyChangeListener(PropertyChangeListener pcl);
public void removePropertyChangeListener(PropertyChangeListener pcl);
void close() throws TskCoreException;
@Override
public String toString();
DatabaseType getDatabaseType();
}
/**
* Instances of this class represent hash databases used to classify files
* as known or know bad.
*/
public static class HashDb implements HashDatabase{
/** /**
* Indicates how files with hashes stored in a particular hash database * Indicates how files with hashes stored in a particular hash database
@ -863,6 +718,81 @@ public class HashDbManager implements PropertyChangeListener {
INDEXING_DONE INDEXING_DONE
} }
public abstract String getHashSetName();
abstract String getDisplayName();
public abstract String getDatabasePath() throws TskCoreException;
public abstract HashDb.KnownFilesType getKnownFilesType();
public abstract boolean getSearchDuringIngest();
abstract boolean getDefaultSearchDuringIngest();
abstract void setSearchDuringIngest(boolean useForIngest);
public abstract boolean getSendIngestMessages();
abstract void setSendIngestMessages(boolean showInboxMessages);
/**
* Indicates whether the hash database accepts updates.
*
* @return True if the database accepts updates, false otherwise.
*
* @throws org.sleuthkit.datamodel.TskCoreException
*/
public abstract boolean isUpdateable() throws TskCoreException;
/**
* Adds hashes of content (if calculated) to the hash database.
*
* @param content The content for which the calculated hashes, if any,
* are to be added to the hash database.
*
* @throws TskCoreException
*/
public abstract void addHashes(Content content) throws TskCoreException;
public abstract void addHashes(Content content, String comment) throws TskCoreException;
public abstract void addHashes(List<HashEntry> hashes) throws TskCoreException;
public abstract boolean lookupMD5Quick(Content content) throws TskCoreException;
public abstract HashHitInfo lookupMD5(Content content) throws TskCoreException;
/**
* Returns whether this database can be enabled.
* For file type, this is the same as checking that it has an index
* @return true if is valid, false otherwise
* @throws TskCoreException
*/
abstract boolean isValid() throws TskCoreException;
public abstract String getIndexPath() throws TskCoreException;
public abstract boolean hasIndexOnly() throws TskCoreException;
public abstract void firePropertyChange(String propertyName, Object oldValue, Object newValue);
public abstract void addPropertyChangeListener(PropertyChangeListener pcl);
public abstract void removePropertyChangeListener(PropertyChangeListener pcl);
@Override
public abstract String toString();
}
/**
* Instances of this class represent hash databases used to classify files
* as known or know bad.
*/
class SleuthkitHashSet extends HashDb{
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final int handle; private final int handle;
private final String hashSetName; private final String hashSetName;
@ -872,7 +802,7 @@ public class HashDbManager implements PropertyChangeListener {
private boolean indexing; private boolean indexing;
private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
private HashDb(int handle, String hashSetName, boolean useForIngest, boolean sendHitMessages, KnownFilesType knownFilesType) { private SleuthkitHashSet(int handle, String hashSetName, boolean useForIngest, boolean sendHitMessages, KnownFilesType knownFilesType) {
this.handle = handle; this.handle = handle;
this.hashSetName = hashSetName; this.hashSetName = hashSetName;
this.searchDuringIngest = useForIngest; this.searchDuringIngest = useForIngest;
@ -902,8 +832,7 @@ public class HashDbManager implements PropertyChangeListener {
propertyChangeSupport.removePropertyChangeListener(pcl); propertyChangeSupport.removePropertyChangeListener(pcl);
} }
@Override int getHandle(){
public int getHandle(){
return handle; return handle;
} }
@ -913,7 +842,7 @@ public class HashDbManager implements PropertyChangeListener {
} }
@Override @Override
public String getDisplayName(){ String getDisplayName(){
return getHashSetName(); return getHashSetName();
} }
@ -927,10 +856,6 @@ public class HashDbManager implements PropertyChangeListener {
} }
@Override @Override
public DatabaseType getDatabaseType(){
return DatabaseType.FILE;
}
public String getIndexPath() throws TskCoreException { public String getIndexPath() throws TskCoreException {
return SleuthkitJNI.getHashDatabaseIndexPath(handle); return SleuthkitJNI.getHashDatabaseIndexPath(handle);
} }
@ -946,13 +871,13 @@ public class HashDbManager implements PropertyChangeListener {
} }
@Override @Override
public boolean getDefaultSearchDuringIngest(){ boolean getDefaultSearchDuringIngest(){
// File type hash sets are on by default // File type hash sets are on by default
return true; return true;
} }
@Override @Override
public void setSearchDuringIngest(boolean useForIngest) { void setSearchDuringIngest(boolean useForIngest) {
this.searchDuringIngest = useForIngest; this.searchDuringIngest = useForIngest;
} }
@ -962,7 +887,7 @@ public class HashDbManager implements PropertyChangeListener {
} }
@Override @Override
public void setSendIngestMessages(boolean showInboxMessages) { void setSendIngestMessages(boolean showInboxMessages) {
this.sendIngestMessages = showInboxMessages; this.sendIngestMessages = showInboxMessages;
} }
@ -1077,23 +1002,24 @@ public class HashDbManager implements PropertyChangeListener {
* @throws TskCoreException * @throws TskCoreException
*/ */
@Override @Override
public boolean isValid() throws TskCoreException { boolean isValid() throws TskCoreException {
return hasIndex(); return hasIndex();
} }
public boolean hasIndex() throws TskCoreException { boolean hasIndex() throws TskCoreException {
return SleuthkitJNI.hashDatabaseHasLookupIndex(handle); return SleuthkitJNI.hashDatabaseHasLookupIndex(handle);
} }
@Override
public boolean hasIndexOnly() throws TskCoreException { public boolean hasIndexOnly() throws TskCoreException {
return SleuthkitJNI.hashDatabaseIsIndexOnly(handle); return SleuthkitJNI.hashDatabaseIsIndexOnly(handle);
} }
public boolean canBeReIndexed() throws TskCoreException { boolean canBeReIndexed() throws TskCoreException {
return SleuthkitJNI.hashDatabaseCanBeReindexed(handle); return SleuthkitJNI.hashDatabaseCanBeReindexed(handle);
} }
public boolean isIndexing() { boolean isIndexing() {
return indexing; return indexing;
} }
@ -1102,8 +1028,7 @@ public class HashDbManager implements PropertyChangeListener {
this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue); this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
} }
@Override private void close() throws TskCoreException {
public void close() throws TskCoreException {
SleuthkitJNI.closeHashDatabase(handle); SleuthkitJNI.closeHashDatabase(handle);
} }
@ -1131,7 +1056,7 @@ public class HashDbManager implements PropertyChangeListener {
if (getClass() != obj.getClass()) { if (getClass() != obj.getClass()) {
return false; return false;
} }
final HashDb other = (HashDb) obj; final SleuthkitHashSet other = (SleuthkitHashSet) obj;
if (!Objects.equals(this.hashSetName, other.hashSetName)) { if (!Objects.equals(this.hashSetName, other.hashSetName)) {
return false; return false;
} }
@ -1146,7 +1071,7 @@ public class HashDbManager implements PropertyChangeListener {
* Instances of this class represent hash databases used to classify files * Instances of this class represent hash databases used to classify files
* as known or know bad. * as known or know bad.
*/ */
public static class CentralRepoHashDb implements HashDatabase{ class CentralRepoHashSet extends HashDb{
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final String hashSetName; private final String hashSetName;
@ -1160,7 +1085,7 @@ public class HashDbManager implements PropertyChangeListener {
private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
@Messages({"HashDbManager.CentralRepoHashDb.orgError=Error loading organization"}) @Messages({"HashDbManager.CentralRepoHashDb.orgError=Error loading organization"})
private CentralRepoHashDb(String hashSetName, String version, int referenceSetID, private CentralRepoHashSet(String hashSetName, String version, int referenceSetID,
boolean useForIngest, boolean sendHitMessages, HashDb.KnownFilesType knownFilesType, boolean useForIngest, boolean sendHitMessages, HashDb.KnownFilesType knownFilesType,
boolean readOnly) boolean readOnly)
throws TskCoreException{ throws TskCoreException{
@ -1175,7 +1100,7 @@ public class HashDbManager implements PropertyChangeListener {
try{ try{
orgName = EamDb.getInstance().getReferenceSetOrganization(referenceSetID).getName(); orgName = EamDb.getInstance().getReferenceSetOrganization(referenceSetID).getName();
} catch (EamDbException ex){ } catch (EamDbException ex){
Logger.getLogger(HashDb.class.getName()).log(Level.SEVERE, "Error looking up central repository organization", ex); //NON-NLS Logger.getLogger(SleuthkitHashSet.class.getName()).log(Level.SEVERE, "Error looking up central repository organization for reference set " + referenceSetID, ex); //NON-NLS
orgName = Bundle.HashDbManager_CentralRepoHashDb_orgError(); orgName = Bundle.HashDbManager_CentralRepoHashDb_orgError();
} }
} }
@ -1202,8 +1127,8 @@ public class HashDbManager implements PropertyChangeListener {
} }
@Override @Override
public int getHandle(){ public boolean hasIndexOnly() throws TskCoreException{
return 0; return true;
} }
@Override @Override
@ -1220,15 +1145,15 @@ public class HashDbManager implements PropertyChangeListener {
} }
} }
public String getVersion(){ String getVersion(){
return version; return version;
} }
public String getOrgName(){ String getOrgName(){
return orgName; return orgName;
} }
public int getReferenceSetID(){ int getReferenceSetID(){
return referenceSetID; return referenceSetID;
} }
@ -1238,10 +1163,6 @@ public class HashDbManager implements PropertyChangeListener {
} }
@Override @Override
public DatabaseType getDatabaseType(){
return DatabaseType.CENTRAL_REPOSITORY;
}
public String getIndexPath() throws TskCoreException { public String getIndexPath() throws TskCoreException {
return ""; return "";
} }
@ -1257,13 +1178,13 @@ public class HashDbManager implements PropertyChangeListener {
} }
@Override @Override
public boolean getDefaultSearchDuringIngest(){ boolean getDefaultSearchDuringIngest(){
// Central repo hash sets are off by default // Central repo hash sets are off by default
return false; return false;
} }
@Override @Override
public void setSearchDuringIngest(boolean useForIngest) { void setSearchDuringIngest(boolean useForIngest) {
this.searchDuringIngest = useForIngest; this.searchDuringIngest = useForIngest;
} }
@ -1273,7 +1194,7 @@ public class HashDbManager implements PropertyChangeListener {
} }
@Override @Override
public void setSendIngestMessages(boolean showInboxMessages) { void setSendIngestMessages(boolean showInboxMessages) {
this.sendIngestMessages = showInboxMessages; this.sendIngestMessages = showInboxMessages;
} }
@ -1381,9 +1302,10 @@ public class HashDbManager implements PropertyChangeListener {
AbstractFile file = (AbstractFile) content; AbstractFile file = (AbstractFile) content;
if (null != file.getMd5Hash()) { if (null != file.getMd5Hash()) {
try{ try{
return EamDb.getInstance().isHashInReferenceSet(file.getMd5Hash(), this.referenceSetID); return EamDb.getInstance().isFileHashInReferenceSet(file.getMd5Hash(), this.referenceSetID);
} catch (EamDbException ex){ } catch (EamDbException ex){
Logger.getLogger(HashDb.class.getName()).log(Level.SEVERE, "Error performing central reposiotry hash lookup", ex); //NON-NLS Logger.getLogger(SleuthkitHashSet.class.getName()).log(Level.SEVERE, "Error performing central reposiotry hash lookup for hash "
+ file.getMd5Hash() + " in reference set " + referenceSetID, ex); //NON-NLS
throw new TskCoreException("Error performing central reposiotry hash lookup", ex); throw new TskCoreException("Error performing central reposiotry hash lookup", ex);
} }
} }
@ -1409,12 +1331,13 @@ public class HashDbManager implements PropertyChangeListener {
AbstractFile file = (AbstractFile) content; AbstractFile file = (AbstractFile) content;
if (null != file.getMd5Hash()) { if (null != file.getMd5Hash()) {
try{ try{
if(EamDb.getInstance().isHashInReferenceSet(file.getMd5Hash(), this.referenceSetID)){ if(EamDb.getInstance().isFileHashInReferenceSet(file.getMd5Hash(), this.referenceSetID)){
// Make a bare-bones HashHitInfo for now // Make a bare-bones HashHitInfo for now
result = new HashHitInfo(file.getMd5Hash(), "", ""); result = new HashHitInfo(file.getMd5Hash(), "", "");
} }
} catch (EamDbException ex){ } catch (EamDbException ex){
Logger.getLogger(HashDb.class.getName()).log(Level.SEVERE, "Error performing central reposiotry hash lookup", ex); //NON-NLS Logger.getLogger(SleuthkitHashSet.class.getName()).log(Level.SEVERE, "Error performing central reposiotry hash lookup for hash "
+ file.getMd5Hash() + " in reference set " + referenceSetID, ex); //NON-NLS
throw new TskCoreException("Error performing central reposiotry hash lookup", ex); throw new TskCoreException("Error performing central reposiotry hash lookup", ex);
} }
} }
@ -1426,17 +1349,16 @@ public class HashDbManager implements PropertyChangeListener {
* Returns whether this database can be enabled. * Returns whether this database can be enabled.
* *
* @return true if is valid, false otherwise * @return true if is valid, false otherwise
* @throws TskCoreException
*/ */
@Override @Override
public boolean isValid() { boolean isValid() {
if(! EamDb.isEnabled()) { if(! EamDb.isEnabled()) {
return false; return false;
} }
try{ try{
return EamDb.getInstance().referenceSetIsValid(this.referenceSetID, this.hashSetName, this.version); return EamDb.getInstance().referenceSetIsValid(this.referenceSetID, this.hashSetName, this.version);
} catch (EamDbException ex){ } catch (EamDbException ex){
Logger.getLogger(CentralRepoHashDb.class.getName()).log(Level.SEVERE, "Error validating hash database " + hashSetName, ex); //NON-NLS Logger.getLogger(CentralRepoHashSet.class.getName()).log(Level.SEVERE, "Error validating hash database " + hashSetName, ex); //NON-NLS
return false; return false;
} }
} }
@ -1446,11 +1368,6 @@ public class HashDbManager implements PropertyChangeListener {
this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue); this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
} }
@Override
public void close() throws TskCoreException {
}
@Override @Override
public String toString(){ public String toString(){
return getDisplayName(); return getDisplayName();
@ -1475,7 +1392,7 @@ public class HashDbManager implements PropertyChangeListener {
if (getClass() != obj.getClass()) { if (getClass() != obj.getClass()) {
return false; return false;
} }
final CentralRepoHashDb other = (CentralRepoHashDb) obj; final CentralRepoHashSet other = (CentralRepoHashSet) obj;
if (!Objects.equals(this.hashSetName, other.hashSetName)) { if (!Objects.equals(this.hashSetName, other.hashSetName)) {
return false; return false;
} }
@ -1495,9 +1412,9 @@ public class HashDbManager implements PropertyChangeListener {
private class HashDbIndexer extends SwingWorker<Object, Void> { private class HashDbIndexer extends SwingWorker<Object, Void> {
private ProgressHandle progress = null; private ProgressHandle progress = null;
private HashDb hashDb = null; private SleuthkitHashSet hashDb = null;
HashDbIndexer(HashDb hashDb) { HashDbIndexer(SleuthkitHashSet hashDb) {
this.hashDb = hashDb; this.hashDb = hashDb;
} }
@ -1511,7 +1428,7 @@ public class HashDbManager implements PropertyChangeListener {
try { try {
SleuthkitJNI.createLookupIndexForHashDatabase(hashDb.getHandle()); SleuthkitJNI.createLookupIndexForHashDatabase(hashDb.getHandle());
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
Logger.getLogger(HashDb.class.getName()).log(Level.SEVERE, "Error indexing hash database", ex); //NON-NLS Logger.getLogger(HashDbIndexer.class.getName()).log(Level.SEVERE, "Error indexing hash set " + hashDb.getHashSetName(), ex); //NON-NLS
JOptionPane.showMessageDialog(null, JOptionPane.showMessageDialog(null,
NbBundle.getMessage(this.getClass(), NbBundle.getMessage(this.getClass(),
"HashDbManager.dlgMsg.errorIndexingHashSet", "HashDbManager.dlgMsg.errorIndexingHashSet",
@ -1541,7 +1458,7 @@ public class HashDbManager implements PropertyChangeListener {
} }
try { try {
hashDb.firePropertyChange(HashDb.Event.INDEXING_DONE.toString(), null, hashDb); hashDb.firePropertyChange(SleuthkitHashSet.Event.INDEXING_DONE.toString(), null, hashDb);
hashDb.firePropertyChange(HashDbManager.SetEvt.DB_INDEXED.toString(), null, hashDb.getHashSetName()); hashDb.firePropertyChange(HashDbManager.SetEvt.DB_INDEXED.toString(), null, hashDb.getHashSetName());
} catch (Exception e) { } catch (Exception e) {
logger.log(Level.SEVERE, "HashDbManager listener threw exception", e); //NON-NLS logger.log(Level.SEVERE, "HashDbManager listener threw exception", e); //NON-NLS

View File

@ -60,7 +60,7 @@ public class HashLookupModuleFactory extends IngestModuleFactoryAdapter {
@Override @Override
public IngestModuleIngestJobSettings getDefaultIngestJobSettings() { public IngestModuleIngestJobSettings getDefaultIngestJobSettings() {
// All available hash sets are enabled and always calculate hashes is true by default. // All available hash sets are enabled and always calculate hashes is true by default.
return new HashLookupModuleSettings(true, HashDbManager.getInstance().refreshAndGetAllHashDatabases()); return new HashLookupModuleSettings(true, HashDbManager.getInstance().getAllHashSets());
} }
@Override @Override

View File

@ -26,8 +26,8 @@ import java.io.IOException;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase;
import org.sleuthkit.autopsy.modules.hashdatabase.HashLookupSettings.HashDbInfo; import org.sleuthkit.autopsy.modules.hashdatabase.HashLookupSettings.HashDbInfo;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
/** /**
* Ingest job settings for the hash lookup module. * Ingest job settings for the hash lookup module.
@ -42,7 +42,7 @@ final class HashLookupModuleSettings implements IngestModuleIngestJobSettings {
private boolean shouldCalculateHashes = true; private boolean shouldCalculateHashes = true;
private List<HashDbInfo> databaseInfoList; private List<HashDbInfo> databaseInfoList;
HashLookupModuleSettings(boolean shouldCalculateHashes, List<HashDatabase> hashDbList){ HashLookupModuleSettings(boolean shouldCalculateHashes, List<HashDb> hashDbList){
this.shouldCalculateHashes = shouldCalculateHashes; this.shouldCalculateHashes = shouldCalculateHashes;
try{ try{
databaseInfoList = HashLookupSettings.convertHashSetList(hashDbList); databaseInfoList = HashLookupSettings.convertHashSetList(hashDbList);
@ -76,12 +76,12 @@ final class HashLookupModuleSettings implements IngestModuleIngestJobSettings {
* @param disabledHashSets A list of disabled hash sets. * @param disabledHashSets A list of disabled hash sets.
*/ */
HashLookupModuleSettings(boolean shouldCalculateHashes, HashLookupModuleSettings(boolean shouldCalculateHashes,
List<HashDatabase> enabledHashSets, List<HashDb> enabledHashSets,
List<HashDatabase> disabledHashSets) { List<HashDb> disabledHashSets) {
this.shouldCalculateHashes = shouldCalculateHashes; this.shouldCalculateHashes = shouldCalculateHashes;
databaseInfoList = new ArrayList<>(); databaseInfoList = new ArrayList<>();
for(HashDatabase db:enabledHashSets){ for(HashDb db:enabledHashSets){
try{ try{
HashDbInfo dbInfo = new HashDbInfo(db); HashDbInfo dbInfo = new HashDbInfo(db);
dbInfo.setSearchDuringIngest(true); dbInfo.setSearchDuringIngest(true);
@ -90,7 +90,7 @@ final class HashLookupModuleSettings implements IngestModuleIngestJobSettings {
Logger.getLogger(HashLookupModuleSettings.class.getName()).log(Level.SEVERE, "Error creating hash database settings for " + db.getHashSetName(), ex); //NON-NLS Logger.getLogger(HashLookupModuleSettings.class.getName()).log(Level.SEVERE, "Error creating hash database settings for " + db.getHashSetName(), ex); //NON-NLS
} }
} }
for(HashDatabase db:disabledHashSets){ for(HashDb db:disabledHashSets){
try{ try{
HashDbInfo dbInfo = new HashDbInfo(db); HashDbInfo dbInfo = new HashDbInfo(db);
dbInfo.setSearchDuringIngest(false); dbInfo.setSearchDuringIngest(false);
@ -128,7 +128,7 @@ final class HashLookupModuleSettings implements IngestModuleIngestJobSettings {
* *
* @return True if the hash set is enabled, false otherwise. * @return True if the hash set is enabled, false otherwise.
*/ */
boolean isHashSetEnabled(HashDatabase db) { boolean isHashSetEnabled(HashDb db) {
for(HashDbInfo dbInfo:databaseInfoList){ for(HashDbInfo dbInfo:databaseInfoList){
if(dbInfo.matches(db)){ if(dbInfo.matches(db)){
return dbInfo.getSearchDuringIngest(); return dbInfo.getSearchDuringIngest();
@ -150,7 +150,7 @@ final class HashLookupModuleSettings implements IngestModuleIngestJobSettings {
} }
try{ try{
databaseInfoList = HashLookupSettings.convertHashSetList(HashDbManager.getInstance().getAllHashDatabases()); databaseInfoList = HashLookupSettings.convertHashSetList(HashDbManager.getInstance().getAllHashSets());
} catch (HashLookupSettings.HashLookupSettingsException ex){ } catch (HashLookupSettings.HashLookupSettingsException ex){
Logger.getLogger(HashLookupModuleSettings.class.getName()).log(Level.SEVERE, "Error updating hash database settings.", ex); //NON-NLS Logger.getLogger(HashLookupModuleSettings.class.getName()).log(Level.SEVERE, "Error updating hash database settings.", ex); //NON-NLS
return; return;

View File

@ -30,8 +30,8 @@ import javax.swing.table.TableColumn;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
/** /**
@ -53,18 +53,13 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe
} }
private void initializeHashSetModels(HashLookupModuleSettings settings) { private void initializeHashSetModels(HashLookupModuleSettings settings) {
try{ initializeHashSetModels(settings, hashDbManager.getKnownFileHashSets(), knownHashSetModels);
hashDbManager.updateHashSetsFromCentralRepository(); initializeHashSetModels(settings, hashDbManager.getKnownBadFileHashSets(), knownBadHashSetModels);
} catch (TskCoreException ex){
Logger.getLogger(HashLookupModuleSettingsPanel.class.getName()).log(Level.SEVERE, "Error updating central repository hash sets", ex); //NON-NLS
}
initializeHashSetModels(settings, hashDbManager.getKnownFileHashDatabases(), knownHashSetModels);
initializeHashSetModels(settings, hashDbManager.getNotableFileHashDatabases(), knownBadHashSetModels);
} }
private void initializeHashSetModels(HashLookupModuleSettings settings, List<HashDatabase> hashDbs, List<HashSetModel> hashSetModels) { private void initializeHashSetModels(HashLookupModuleSettings settings, List<HashDb> hashDbs, List<HashSetModel> hashSetModels) {
hashSetModels.clear(); hashSetModels.clear();
for (HashDatabase db : hashDbs) { for (HashDb db : hashDbs) {
hashSetModels.add(new HashSetModel(db, settings.isHashSetEnabled(db), isHashDbValid(db))); hashSetModels.add(new HashSetModel(db, settings.isHashSetEnabled(db), isHashDbValid(db)));
} }
} }
@ -105,15 +100,15 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe
@Override @Override
public IngestModuleIngestJobSettings getSettings() { public IngestModuleIngestJobSettings getSettings() {
List<HashDatabase> enabledHashSets = new ArrayList<>(); List<HashDb> enabledHashSets = new ArrayList<>();
List<HashDatabase> disabledHashSets = new ArrayList<>(); List<HashDb> disabledHashSets = new ArrayList<>();
addHashSets(knownHashSetModels, enabledHashSets, disabledHashSets); addHashSets(knownHashSetModels, enabledHashSets, disabledHashSets);
addHashSets(knownBadHashSetModels, enabledHashSets, disabledHashSets); addHashSets(knownBadHashSetModels, enabledHashSets, disabledHashSets);
return new HashLookupModuleSettings(alwaysCalcHashesCheckbox.isSelected(), return new HashLookupModuleSettings(alwaysCalcHashesCheckbox.isSelected(),
enabledHashSets, disabledHashSets); enabledHashSets, disabledHashSets);
} }
private void addHashSets(List<HashSetModel> hashSetModels, List<HashDatabase> enabledHashSets, List<HashDatabase> disabledHashSets) { private void addHashSets(List<HashSetModel> hashSetModels, List<HashDb> enabledHashSets, List<HashDb> disabledHashSets) {
for (HashSetModel model : hashSetModels) { for (HashSetModel model : hashSetModels) {
if (model.isEnabled() && model.isValid()) { if (model.isEnabled() && model.isValid()) {
enabledHashSets.add(model.getDatabase()); enabledHashSets.add(model.getDatabase());
@ -130,19 +125,19 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe
} }
private void updateHashSetModels() { private void updateHashSetModels() {
updateHashSetModels(hashDbManager.getKnownFileHashDatabases(), knownHashSetModels); updateHashSetModels(hashDbManager.getKnownFileHashSets(), knownHashSetModels);
updateHashSetModels(hashDbManager.getNotableFileHashDatabases(), knownBadHashSetModels); updateHashSetModels(hashDbManager.getKnownBadFileHashSets(), knownBadHashSetModels);
} }
void updateHashSetModels(List<HashDatabase> hashDbs, List<HashSetModel> hashSetModels) { void updateHashSetModels(List<HashDb> hashDbs, List<HashSetModel> hashSetModels) {
List<HashDatabase> hashDatabases = new ArrayList<>(hashDbs); List<HashDb> hashDatabases = new ArrayList<>(hashDbs);
// Update the hash sets and detect deletions. // Update the hash sets and detect deletions.
List<HashSetModel> deletedHashSetModels = new ArrayList<>(); List<HashSetModel> deletedHashSetModels = new ArrayList<>();
for (HashSetModel model : hashSetModels) { for (HashSetModel model : hashSetModels) {
boolean foundDatabase = false; boolean foundDatabase = false;
for(HashDatabase db : hashDatabases){ for(HashDb db : hashDatabases){
if(model.getDatabase().equals(db)){ if(model.getDatabase().equals(db)){
model.setValid(isHashDbValid(db)); model.setValid(isHashDbValid(db));
hashDatabases.remove(db); hashDatabases.remove(db);
@ -161,7 +156,7 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe
} }
// Add any new hash sets. All new sets are enabled by default. // Add any new hash sets. All new sets are enabled by default.
for (HashDatabase db : hashDatabases) { for (HashDb db : hashDatabases) {
hashSetModels.add(new HashSetModel(db, true, isHashDbValid(db))); hashSetModels.add(new HashSetModel(db, true, isHashDbValid(db)));
} }
} }
@ -173,7 +168,7 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe
knownBadHashSetsTableModel.fireTableDataChanged(); knownBadHashSetsTableModel.fireTableDataChanged();
} }
private boolean isHashDbValid(HashDatabase hashDb) { private boolean isHashDbValid(HashDb hashDb) {
boolean isValid = false; boolean isValid = false;
try { try {
isValid = hashDb.isValid(); isValid = hashDb.isValid();
@ -185,17 +180,17 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe
private static final class HashSetModel { private static final class HashSetModel {
private final HashDatabase db; private final HashDb db;
private boolean valid; private boolean valid;
private boolean enabled; private boolean enabled;
HashSetModel(HashDatabase db, boolean enabled, boolean valid) { HashSetModel(HashDb db, boolean enabled, boolean valid) {
this.db = db; this.db = db;
this.enabled = enabled; this.enabled = enabled;
this.valid = valid; this.valid = valid;
} }
HashDatabase getDatabase(){ HashDb getDatabase(){
return db; return db;
} }

View File

@ -36,13 +36,13 @@ import org.sleuthkit.autopsy.core.RuntimeProperties;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.coreutils.XMLUtil; import org.sleuthkit.autopsy.coreutils.XMLUtil;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.CentralRepoHashSet;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase.DatabaseType; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.SleuthkitHashSet;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.CentralRepoHashDb;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
/** /**
* Class to represent the settings to be serialized for hash lookup. * Class to represent the settings to be serialized for hash lookup.
@ -74,9 +74,9 @@ final class HashLookupSettings implements Serializable {
this.hashDbInfoList = hashDbInfoList; this.hashDbInfoList = hashDbInfoList;
} }
static List<HashDbInfo> convertHashSetList(List<HashDbManager.HashDatabase> hashSets) throws HashLookupSettingsException{ static List<HashDbInfo> convertHashSetList(List<HashDbManager.HashDb> hashSets) throws HashLookupSettingsException{
List<HashDbInfo> dbInfoList = new ArrayList<>(); List<HashDbInfo> dbInfoList = new ArrayList<>();
for(HashDbManager.HashDatabase db:hashSets){ for(HashDbManager.HashDb db:hashSets){
try{ try{
dbInfoList.add(new HashDbInfo(db)); dbInfoList.add(new HashDbInfo(db));
} catch (TskCoreException ex){ } catch (TskCoreException ex){
@ -297,6 +297,11 @@ final class HashLookupSettings implements Serializable {
*/ */
static final class HashDbInfo implements Serializable { static final class HashDbInfo implements Serializable {
enum DatabaseType{
FILE,
CENTRAL_REPOSITORY
};
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final String hashSetName; private final String hashSetName;
private final HashDbManager.HashDb.KnownFilesType knownFilesType; private final HashDbManager.HashDb.KnownFilesType knownFilesType;
@ -342,9 +347,9 @@ final class HashLookupSettings implements Serializable {
dbType = DatabaseType.CENTRAL_REPOSITORY; dbType = DatabaseType.CENTRAL_REPOSITORY;
} }
HashDbInfo(HashDbManager.HashDatabase db) throws TskCoreException{ HashDbInfo(HashDbManager.HashDb db) throws TskCoreException{
if(db instanceof HashDbManager.HashDb){ if(db instanceof HashDbManager.SleuthkitHashSet){
HashDbManager.HashDb fileTypeDb = (HashDbManager.HashDb)db; HashDbManager.SleuthkitHashSet fileTypeDb = (HashDbManager.SleuthkitHashSet)db;
this.hashSetName = fileTypeDb.getHashSetName(); this.hashSetName = fileTypeDb.getHashSetName();
this.knownFilesType = fileTypeDb.getKnownFilesType(); this.knownFilesType = fileTypeDb.getKnownFilesType();
this.searchDuringIngest = fileTypeDb.getSearchDuringIngest(); this.searchDuringIngest = fileTypeDb.getSearchDuringIngest();
@ -359,7 +364,7 @@ final class HashLookupSettings implements Serializable {
this.path = fileTypeDb.getDatabasePath(); this.path = fileTypeDb.getDatabasePath();
} }
} else { } else {
HashDbManager.CentralRepoHashDb centralRepoDb = (HashDbManager.CentralRepoHashDb)db; HashDbManager.CentralRepoHashSet centralRepoDb = (HashDbManager.CentralRepoHashSet)db;
this.hashSetName = centralRepoDb.getHashSetName(); this.hashSetName = centralRepoDb.getHashSetName();
this.version = centralRepoDb.getVersion(); this.version = centralRepoDb.getVersion();
this.knownFilesType = centralRepoDb.getKnownFilesType(); this.knownFilesType = centralRepoDb.getKnownFilesType();
@ -457,7 +462,7 @@ final class HashLookupSettings implements Serializable {
return dbType == DatabaseType.CENTRAL_REPOSITORY; return dbType == DatabaseType.CENTRAL_REPOSITORY;
} }
boolean matches(HashDatabase hashDb){ boolean matches(HashDb hashDb){
if(hashDb == null){ if(hashDb == null){
return false; return false;
} }
@ -466,7 +471,8 @@ final class HashLookupSettings implements Serializable {
return false; return false;
} }
if( ! this.dbType.equals(hashDb.getDatabaseType())){ if((this.dbType == DatabaseType.CENTRAL_REPOSITORY) && (! (hashDb instanceof CentralRepoHashSet))
|| (this.dbType == DatabaseType.FILE) && (! (hashDb instanceof SleuthkitHashSet))){
return false; return false;
} }
@ -474,19 +480,15 @@ final class HashLookupSettings implements Serializable {
return false; return false;
} }
if(this.dbType.equals(DatabaseType.FILE)){ if(hashDb instanceof CentralRepoHashSet){
// FILE types will always have unique names, so no more testing required CentralRepoHashSet crDb = (CentralRepoHashSet) hashDb;
return true; if(this.referenceSetID != crDb.getReferenceSetID()){
} return false;
}
// Central repo tests if(! version.equals(crDb.getVersion())){
CentralRepoHashDb crDb = (CentralRepoHashDb) hashDb; return false;
if(this.referenceSetID != crDb.getReferenceSetID()){ }
return false;
}
if(! version.equals(crDb.getVersion())){
return false;
} }
return true; return true;

View File

@ -27,7 +27,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.JTable; import javax.swing.JTable;
import javax.swing.ListSelectionModel; import javax.swing.ListSelectionModel;
@ -46,11 +45,11 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.events.AutopsyEvent; import org.sleuthkit.autopsy.events.AutopsyEvent;
import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel; import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.SleuthkitHashSet;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.CentralRepoHashDb; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.CentralRepoHashSet;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
/** /**
* Instances of this class provide a comprehensive UI for managing the hash sets * Instances of this class provide a comprehensive UI for managing the hash sets
@ -109,7 +108,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
} }
private void updateComponents() { private void updateComponents() {
HashDatabase db = ((HashSetTable) hashSetTable).getSelection(); HashDb db = ((HashSetTable) hashSetTable).getSelection();
if (db != null) { if (db != null) {
updateComponentsForSelection(db); updateComponentsForSelection(db);
} else { } else {
@ -158,7 +157,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
"HashLookupSettingsPanel.notApplicable=N/A", "HashLookupSettingsPanel.notApplicable=N/A",
"HashLookupSettingsPanel.centralRepo=Central Repository" "HashLookupSettingsPanel.centralRepo=Central Repository"
}) })
private void updateComponentsForSelection(HashDatabase db) { private void updateComponentsForSelection(HashDb db) {
boolean ingestIsRunning = IngestManager.getInstance().isIngestRunning(); boolean ingestIsRunning = IngestManager.getInstance().isIngestRunning();
// Update descriptive labels. // Update descriptive labels.
@ -181,8 +180,8 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
addHashesToDatabaseButton.setEnabled(false); addHashesToDatabaseButton.setEnabled(false);
} }
if(db instanceof HashDb){ if(db instanceof SleuthkitHashSet){
HashDb hashDb = (HashDb)db; SleuthkitHashSet hashDb = (SleuthkitHashSet)db;
// Disable the central repo fields // Disable the central repo fields
hashDbVersionLabel.setText(Bundle.HashLookupSettingsPanel_notApplicable()); hashDbVersionLabel.setText(Bundle.HashLookupSettingsPanel_notApplicable());
@ -254,7 +253,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
indexButton.setEnabled(false); indexButton.setEnabled(false);
deleteDatabaseButton.setEnabled(false); deleteDatabaseButton.setEnabled(false);
CentralRepoHashDb crDb = (CentralRepoHashDb)db; CentralRepoHashSet crDb = (CentralRepoHashSet)db;
hashDbVersionLabel.setText(crDb.getVersion()); hashDbVersionLabel.setText(crDb.getVersion());
hashDbOrgLabel.setText(crDb.getOrgName()); hashDbOrgLabel.setText(crDb.getOrgName());
@ -305,13 +304,13 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
"HashLookupSettingsPanel.saveFail.title=Save Fail"}) "HashLookupSettingsPanel.saveFail.title=Save Fail"})
public void saveSettings() { public void saveSettings() {
//Checking for for any unindexed databases //Checking for for any unindexed databases
List<HashDb> unindexed = new ArrayList<>(); List<SleuthkitHashSet> unindexed = new ArrayList<>();
for (HashDatabase hashSet : hashSetManager.getAllHashDatabases()) { for (HashDb db : hashSetManager.getAllHashSets()) {
if(hashSet instanceof HashDb){ if(db instanceof SleuthkitHashSet){
HashDb db = (HashDb)hashSet;
try { try {
if (!db.hasIndex()) { SleuthkitHashSet hashDatabase = (SleuthkitHashSet)db;
unindexed.add(db); if (!hashDatabase.hasIndex()) {
unindexed.add(hashDatabase);
} }
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
Logger.getLogger(HashLookupSettingsPanel.class.getName()).log(Level.SEVERE, "Error getting index info for hash database", ex); //NON-NLS Logger.getLogger(HashLookupSettingsPanel.class.getName()).log(Level.SEVERE, "Error getting index info for hash database", ex); //NON-NLS
@ -374,8 +373,8 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
} }
@Messages({"# {0} - hash lookup name", "HashLookupSettingsPanel.removeDatabaseFailure.message=Failed to remove hash lookup: {0}"}) @Messages({"# {0} - hash lookup name", "HashLookupSettingsPanel.removeDatabaseFailure.message=Failed to remove hash lookup: {0}"})
void removeThese(List<HashDb> toRemove) { void removeThese(List<SleuthkitHashSet> toRemove) {
for (HashDb hashDb : toRemove) { for (SleuthkitHashSet hashDb : toRemove) {
try { try {
hashSetManager.removeHashDatabaseNoSave(hashDb); hashSetManager.removeHashDatabaseNoSave(hashDb);
} catch (HashDbManager.HashDbManagerException ex) { } catch (HashDbManager.HashDbManagerException ex) {
@ -393,10 +392,10 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
* @param plural Whether or not there are multiple unindexed databases * @param plural Whether or not there are multiple unindexed databases
* @param unindexed The list of unindexed databases. Can be of size 1. * @param unindexed The list of unindexed databases. Can be of size 1.
*/ */
private void showInvalidIndex(boolean plural, List<HashDb> unindexed) { private void showInvalidIndex(boolean plural, List<SleuthkitHashSet> unindexed) {
String total = ""; String total = "";
String message; String message;
for (HashDatabase hdb : unindexed) { for (HashDb hdb : unindexed) {
total += "\n" + hdb.getHashSetName(); total += "\n" + hdb.getHashSetName();
} }
if (plural) { if (plural) {
@ -449,7 +448,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
return cellRenderer; return cellRenderer;
} }
public HashDatabase getSelection() { public HashDb getSelection() {
return hashSetTableModel.getHashSetAt(getSelectionModel().getMinSelectionIndex()); return hashSetTableModel.getHashSetAt(getSelectionModel().getMinSelectionIndex());
} }
@ -459,7 +458,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
} }
} }
public void selectRowByDatabase(HashDatabase db){ public void selectRowByDatabase(HashDb db){
setSelection(hashSetTableModel.getIndexByDatabase(db)); setSelection(hashSetTableModel.getIndexByDatabase(db));
} }
@ -475,7 +474,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
*/ */
private class HashSetTableModel extends AbstractTableModel { private class HashSetTableModel extends AbstractTableModel {
List<HashDatabase> hashSets = HashDbManager.getInstance().getAllHashDatabases(); List<HashDb> hashSets = HashDbManager.getInstance().getAllHashSets();
@Override @Override
public int getColumnCount() { public int getColumnCount() {
@ -522,7 +521,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
return getValueAt(0, c).getClass(); return getValueAt(0, c).getClass();
} }
HashDatabase getHashSetAt(int index) { HashDb getHashSetAt(int index) {
if (!hashSets.isEmpty() && index >= 0 && index < hashSets.size()) { if (!hashSets.isEmpty() && index >= 0 && index < hashSets.size()) {
return hashSets.get(index); return hashSets.get(index);
} else { } else {
@ -530,7 +529,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
} }
} }
int getIndexByDatabase(HashDatabase db){ int getIndexByDatabase(HashDb db){
for (int i = 0; i < hashSets.size(); ++i) { for (int i = 0; i < hashSets.size(); ++i) {
if (hashSets.get(i).equals(db)) { if (hashSets.get(i).equals(db)) {
return i; return i;
@ -550,7 +549,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
} }
void refreshModel() { void refreshModel() {
hashSets = HashDbManager.getInstance().refreshAndGetAllHashDatabases(); hashSets = HashDbManager.getInstance().getAllHashSets();
refreshDisplay(); refreshDisplay();
} }
@ -914,15 +913,15 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
private void addHashesToDatabaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addHashesToDatabaseButtonActionPerformed private void addHashesToDatabaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addHashesToDatabaseButtonActionPerformed
HashDatabase hashDb = ((HashSetTable) hashSetTable).getSelection(); HashDb hashDb = ((HashSetTable) hashSetTable).getSelection();
AddHashValuesToDatabaseDialog dialog = new AddHashValuesToDatabaseDialog(hashDb); AddHashValuesToDatabaseDialog dialog = new AddHashValuesToDatabaseDialog(hashDb);
}//GEN-LAST:event_addHashesToDatabaseButtonActionPerformed }//GEN-LAST:event_addHashesToDatabaseButtonActionPerformed
private void createDatabaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_createDatabaseButtonActionPerformed private void createDatabaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_createDatabaseButtonActionPerformed
HashDatabase hashDb = new HashDbCreateDatabaseDialog().getHashDatabase(); HashDb hashDb = new HashDbCreateDatabaseDialog().getHashDatabase();
if (null != hashDb) { if (null != hashDb) {
if(hashDb instanceof CentralRepoHashDb){ if(hashDb instanceof CentralRepoHashSet){
int newDbIndex = ((CentralRepoHashDb)hashDb).getReferenceSetID(); int newDbIndex = ((CentralRepoHashSet)hashDb).getReferenceSetID();
newReferenceSetIDs.add(newDbIndex); newReferenceSetIDs.add(newDbIndex);
} }
@ -933,7 +932,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
}//GEN-LAST:event_createDatabaseButtonActionPerformed }//GEN-LAST:event_createDatabaseButtonActionPerformed
private void sendIngestMessagesCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sendIngestMessagesCheckBoxActionPerformed private void sendIngestMessagesCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sendIngestMessagesCheckBoxActionPerformed
HashDatabase hashDb = ((HashSetTable) hashSetTable).getSelection(); HashDb hashDb = ((HashSetTable) hashSetTable).getSelection();
if (hashDb != null) { if (hashDb != null) {
hashDb.setSendIngestMessages(sendIngestMessagesCheckBox.isSelected()); hashDb.setSendIngestMessages(sendIngestMessagesCheckBox.isSelected());
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
@ -941,18 +940,18 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
}//GEN-LAST:event_sendIngestMessagesCheckBoxActionPerformed }//GEN-LAST:event_sendIngestMessagesCheckBoxActionPerformed
private void indexButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_indexButtonActionPerformed private void indexButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_indexButtonActionPerformed
final HashDatabase hashDatabase = ((HashSetTable) hashSetTable).getSelection(); final HashDb hashDatabase = ((HashSetTable) hashSetTable).getSelection();
assert hashDatabase != null; assert hashDatabase != null;
assert hashDatabase instanceof HashDb; assert hashDatabase instanceof SleuthkitHashSet;
// Add a listener for the INDEXING_DONE event. This listener will update // Add a listener for the INDEXING_DONE event. This listener will update
// the UI. // the UI.
HashDb hashDb = (HashDb)hashDatabase; SleuthkitHashSet hashDb = (SleuthkitHashSet)hashDatabase;
hashDb.addPropertyChangeListener(new PropertyChangeListener() { hashDb.addPropertyChangeListener(new PropertyChangeListener() {
@Override @Override
public void propertyChange(PropertyChangeEvent evt) { public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(HashDb.Event.INDEXING_DONE.toString())) { if (evt.getPropertyName().equals(SleuthkitHashSet.Event.INDEXING_DONE.toString())) {
HashDatabase selectedHashDb = ((HashSetTable) hashSetTable).getSelection(); HashDb selectedHashDb = ((HashSetTable) hashSetTable).getSelection();
if (selectedHashDb != null && hashDb != null && hashDb.equals(selectedHashDb)) { if (selectedHashDb != null && hashDb != null && hashDb.equals(selectedHashDb)) {
updateComponents(); updateComponents();
} }
@ -973,10 +972,10 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
}//GEN-LAST:event_indexButtonActionPerformed }//GEN-LAST:event_indexButtonActionPerformed
private void importDatabaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importDatabaseButtonActionPerformed private void importDatabaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importDatabaseButtonActionPerformed
HashDatabase hashDb = new HashDbImportDatabaseDialog().getHashDatabase(); HashDb hashDb = new HashDbImportDatabaseDialog().getHashDatabase();
if (null != hashDb) { if (null != hashDb) {
if(hashDb instanceof CentralRepoHashDb){ if(hashDb instanceof CentralRepoHashSet){
int newReferenceSetID = ((CentralRepoHashDb)hashDb).getReferenceSetID(); int newReferenceSetID = ((CentralRepoHashSet)hashDb).getReferenceSetID();
newReferenceSetIDs.add(newReferenceSetID); newReferenceSetIDs.add(newReferenceSetID);
} }
@ -994,7 +993,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
NbBundle.getMessage(this.getClass(), "HashDbConfigPanel.deleteDbActionMsg"), NbBundle.getMessage(this.getClass(), "HashDbConfigPanel.deleteDbActionMsg"),
JOptionPane.YES_NO_OPTION, JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) { JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) {
HashDatabase hashDb = ((HashSetTable) hashSetTable).getSelection(); HashDb hashDb = ((HashSetTable) hashSetTable).getSelection();
if (hashDb != null) { if (hashDb != null) {
try { try {
hashSetManager.removeHashDatabaseNoSave(hashDb); hashSetManager.removeHashDatabaseNoSave(hashDb);
@ -1009,7 +1008,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
private void hashSetTableKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_hashSetTableKeyPressed private void hashSetTableKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_hashSetTableKeyPressed
if (evt.getKeyCode() == KeyEvent.VK_DELETE) { if (evt.getKeyCode() == KeyEvent.VK_DELETE) {
HashDatabase hashDb = ((HashSetTable) hashSetTable).getSelection(); HashDb hashDb = ((HashSetTable) hashSetTable).getSelection();
if (hashDb != null) { if (hashDb != null) {
try { try {
hashSetManager.removeHashDatabaseNoSave(hashDb); hashSetManager.removeHashDatabaseNoSave(hashDb);

View File

@ -39,6 +39,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamGlobalFileInstance; import org.sleuthkit.autopsy.centralrepository.datamodel.EamGlobalFileInstance;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamGlobalSet;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskData;
@ -92,7 +93,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P
this.setVisible(true); this.setVisible(true);
} }
HashDbManager.HashDatabase getDatabase(){ HashDbManager.HashDb getDatabase(){
if(worker != null){ if(worker != null){
return worker.getDatabase(); return worker.getDatabase();
} }
@ -128,7 +129,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P
void addPropertyChangeListener(PropertyChangeListener dialog); void addPropertyChangeListener(PropertyChangeListener dialog);
int getProgressPercentage(); int getProgressPercentage();
long getLinesProcessed(); long getLinesProcessed();
HashDbManager.HashDatabase getDatabase(); HashDbManager.HashDb getDatabase();
} }
class ImportIDXWorker extends SwingWorker<Void,Void> implements CentralRepoImportWorker{ class ImportIDXWorker extends SwingWorker<Void,Void> implements CentralRepoImportWorker{
@ -144,7 +145,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P
private final File importFile; private final File importFile;
private final long totalLines; private final long totalLines;
private int referenceSetID = -1; private int referenceSetID = -1;
private HashDbManager.CentralRepoHashDb newHashDb = null; private HashDbManager.CentralRepoHashSet newHashDb = null;
private final AtomicLong numLines = new AtomicLong(); private final AtomicLong numLines = new AtomicLong();
ImportIDXWorker(String hashSetName, String version, int orgId, ImportIDXWorker(String hashSetName, String version, int orgId,
@ -176,7 +177,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P
} }
@Override @Override
public HashDbManager.HashDatabase getDatabase(){ public HashDbManager.HashDb getDatabase(){
return newHashDb; return newHashDb;
} }
@ -201,7 +202,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P
} }
// Create an empty hashset in the central repository // Create an empty hashset in the central repository
referenceSetID = EamDb.getInstance().newReferenceSet(orgId, hashSetName, version, knownStatus, readOnly); referenceSetID = EamDb.getInstance().newReferenceSet(new EamGlobalSet(orgId, hashSetName, version, knownStatus, readOnly));
EamDb dbManager = EamDb.getInstance(); EamDb dbManager = EamDb.getInstance();
CorrelationAttribute.Type contentType = dbManager.getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID); // get "FILES" type CorrelationAttribute.Type contentType = dbManager.getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID); // get "FILES" type

View File

@ -26,7 +26,7 @@ import java.util.List;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.SleuthkitHashSet;
/** /**
* This class exists as a stop-gap measure to force users to have an indexed * This class exists as a stop-gap measure to force users to have an indexed
@ -43,8 +43,8 @@ import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
*/ */
class ModalNoButtons extends javax.swing.JDialog implements PropertyChangeListener { class ModalNoButtons extends javax.swing.JDialog implements PropertyChangeListener {
List<HashDb> unindexed; List<SleuthkitHashSet> unindexed;
HashDb toIndex; SleuthkitHashSet toIndex;
HashLookupSettingsPanel hdbmp; HashLookupSettingsPanel hdbmp;
int length = 0; int length = 0;
int currentcount = 1; int currentcount = 1;
@ -58,7 +58,7 @@ class ModalNoButtons extends javax.swing.JDialog implements PropertyChangeListen
* @param parent Swing parent frame. * @param parent Swing parent frame.
* @param unindexed the list of unindexed databases to index. * @param unindexed the list of unindexed databases to index.
*/ */
ModalNoButtons(HashLookupSettingsPanel hdbmp, java.awt.Frame parent, List<HashDb> unindexed) { ModalNoButtons(HashLookupSettingsPanel hdbmp, java.awt.Frame parent, List<SleuthkitHashSet> unindexed) {
super(parent, NbBundle.getMessage(ModalNoButtons.class, "ModalNoButtons.indexingDbsTitle"), true); super(parent, NbBundle.getMessage(ModalNoButtons.class, "ModalNoButtons.indexingDbsTitle"), true);
this.unindexed = unindexed; this.unindexed = unindexed;
this.toIndex = null; this.toIndex = null;
@ -75,7 +75,7 @@ class ModalNoButtons extends javax.swing.JDialog implements PropertyChangeListen
* @param parent Swing parent frame. * @param parent Swing parent frame.
* @param unindexed The unindexed database to index. * @param unindexed The unindexed database to index.
*/ */
ModalNoButtons(HashLookupSettingsPanel hdbmp, java.awt.Frame parent, HashDb unindexed) { ModalNoButtons(HashLookupSettingsPanel hdbmp, java.awt.Frame parent, SleuthkitHashSet unindexed) {
super(parent, NbBundle.getMessage(ModalNoButtons.class, "ModalNoButtons.indexingDbTitle"), true); super(parent, NbBundle.getMessage(ModalNoButtons.class, "ModalNoButtons.indexingDbTitle"), true);
this.unindexed = null; this.unindexed = null;
this.toIndex = unindexed; this.toIndex = unindexed;
@ -183,7 +183,7 @@ class ModalNoButtons extends javax.swing.JDialog implements PropertyChangeListen
"ModalNoButtons.dlgTitle.unfinishedIndexing"), "ModalNoButtons.dlgTitle.unfinishedIndexing"),
JOptionPane.YES_NO_OPTION); JOptionPane.YES_NO_OPTION);
if (res == JOptionPane.YES_OPTION) { if (res == JOptionPane.YES_OPTION) {
List<HashDb> remove = new ArrayList<>(); List<SleuthkitHashSet> remove = new ArrayList<>();
if (this.toIndex == null) { if (this.toIndex == null) {
remove = this.unindexed; remove = this.unindexed;
} else { } else {
@ -230,7 +230,7 @@ class ModalNoButtons extends javax.swing.JDialog implements PropertyChangeListen
private void indexThese() { private void indexThese() {
length = this.unindexed.size(); length = this.unindexed.size();
this.INDEXING_PROGBAR.setIndeterminate(true); this.INDEXING_PROGBAR.setIndeterminate(true);
for (HashDb db : this.unindexed) { for (SleuthkitHashSet db : this.unindexed) {
currentDb = db.getHashSetName(); currentDb = db.getHashSetName();
this.CURRENTDB_LABEL.setText("(" + currentDb + ")"); this.CURRENTDB_LABEL.setText("(" + currentDb + ")");
this.CURRENTLYON_LABEL.setText( this.CURRENTLYON_LABEL.setText(
@ -255,7 +255,7 @@ class ModalNoButtons extends javax.swing.JDialog implements PropertyChangeListen
* this dialog if all indexing is complete. * this dialog if all indexing is complete.
*/ */
public void propertyChange(PropertyChangeEvent evt) { public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(HashDb.Event.INDEXING_DONE.name())) { if (evt.getPropertyName().equals(SleuthkitHashSet.Event.INDEXING_DONE.name())) {
if (currentcount >= length) { if (currentcount >= length) {
this.INDEXING_PROGBAR.setValue(100); this.INDEXING_PROGBAR.setValue(100);
this.setModal(false); this.setModal(false);

View File

@ -27,6 +27,7 @@ import javax.swing.JPanel;
import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.casemodule.services.TagsManager;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.autopsy.report.GeneralReportModule; import org.sleuthkit.autopsy.report.GeneralReportModule;
import org.sleuthkit.autopsy.report.ReportProgressPanel; import org.sleuthkit.autopsy.report.ReportProgressPanel;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
@ -34,7 +35,6 @@ import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.ContentTag;
import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TagName;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase;
/** /**
* Instances of this class plug in to the reporting infrastructure to provide a * Instances of this class plug in to the reporting infrastructure to provide a
@ -69,7 +69,7 @@ public class AddTaggedHashesToHashDb implements GeneralReportModule {
progressPanel.start(); progressPanel.start();
progressPanel.updateStatusLabel("Adding hashes..."); progressPanel.updateStatusLabel("Adding hashes...");
HashDatabase hashSet = configPanel.getSelectedHashDatabase(); HashDb hashSet = configPanel.getSelectedHashDatabase();
if (hashSet != null) { if (hashSet != null) {
progressPanel.updateStatusLabel("Adding hashes to " + hashSet.getHashSetName() + " hash set..."); progressPanel.updateStatusLabel("Adding hashes to " + hashSet.getHashSetName() + " hash set...");

View File

@ -124,7 +124,7 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="hashSetsComboBoxActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="hashSetsComboBoxActionPerformed"/>
</Events> </Events>
<AuxValues> <AuxValues>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;HashDatabase&gt;"/> <AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;HashDb&gt;"/>
</AuxValues> </AuxValues>
</Component> </Component>
<Component class="javax.swing.JButton" name="configureHashDatabasesButton"> <Component class="javax.swing.JButton" name="configureHashDatabasesButton">

View File

@ -35,11 +35,11 @@ import javax.swing.ListModel;
import javax.swing.event.ListDataListener; import javax.swing.event.ListDataListener;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager;
import org.sleuthkit.autopsy.modules.hashdatabase.HashLookupSettingsPanel; import org.sleuthkit.autopsy.modules.hashdatabase.HashLookupSettingsPanel;
import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TagName;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase;
/** /**
* Instances of this class are used to configure the report module plug in that * Instances of this class are used to configure the report module plug in that
@ -52,7 +52,7 @@ class AddTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel {
private final Map<String, Boolean> tagNameSelections = new LinkedHashMap<>(); private final Map<String, Boolean> tagNameSelections = new LinkedHashMap<>();
private final TagNamesListModel tagsNamesListModel = new TagNamesListModel(); private final TagNamesListModel tagsNamesListModel = new TagNamesListModel();
private final TagsNamesListCellRenderer tagsNamesRenderer = new TagsNamesListCellRenderer(); private final TagsNamesListCellRenderer tagsNamesRenderer = new TagsNamesListCellRenderer();
private HashDatabase selectedHashSet = null; private HashDb selectedHashSet = null;
AddTaggedHashesToHashDbConfigPanel() { AddTaggedHashesToHashDbConfigPanel() {
initComponents(); initComponents();
@ -107,9 +107,9 @@ class AddTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel {
// Get the updateable hash databases and add their hash set names to the // Get the updateable hash databases and add their hash set names to the
// JComboBox component. // JComboBox component.
List<HashDatabase> updateableHashSets = HashDbManager.getInstance().getUpdateableHashDatabases(); List<HashDb> updateableHashSets = HashDbManager.getInstance().getUpdateableHashSets();
if (!updateableHashSets.isEmpty()) { if (!updateableHashSets.isEmpty()) {
for (HashDatabase hashDb : updateableHashSets) { for (HashDb hashDb : updateableHashSets) {
hashSetsComboBox.addItem(hashDb); hashSetsComboBox.addItem(hashDb);
} }
hashSetsComboBox.setEnabled(true); hashSetsComboBox.setEnabled(true);
@ -138,7 +138,7 @@ class AddTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel {
* *
* @return A HashDb object representing the database or null. * @return A HashDb object representing the database or null.
*/ */
HashDatabase getSelectedHashDatabase() { HashDb getSelectedHashDatabase() {
return selectedHashSet; return selectedHashSet;
} }
@ -286,7 +286,7 @@ class AddTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel {
}//GEN-LAST:event_selectAllButtonActionPerformed }//GEN-LAST:event_selectAllButtonActionPerformed
private void hashSetsComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_hashSetsComboBoxActionPerformed private void hashSetsComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_hashSetsComboBoxActionPerformed
selectedHashSet = (HashDatabase)hashSetsComboBox.getSelectedItem(); selectedHashSet = (HashDb)hashSetsComboBox.getSelectedItem();
}//GEN-LAST:event_hashSetsComboBoxActionPerformed }//GEN-LAST:event_hashSetsComboBoxActionPerformed
private void deselectAllButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deselectAllButtonActionPerformed private void deselectAllButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deselectAllButtonActionPerformed
@ -311,7 +311,7 @@ class AddTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel {
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton configureHashDatabasesButton; private javax.swing.JButton configureHashDatabasesButton;
private javax.swing.JButton deselectAllButton; private javax.swing.JButton deselectAllButton;
private javax.swing.JComboBox<HashDatabase> hashSetsComboBox; private javax.swing.JComboBox<HashDb> hashSetsComboBox;
private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel2;
private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane1;

View File

@ -0,0 +1,71 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 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.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import junit.framework.TestCase;
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.openide.util.Exceptions;
public class IngestFileFiltersTest extends TestCase {
private static final Path caseDirectoryPath = Paths.get(System.getProperty("java.io.tmpdir"), "IngestFileFiltersTest");
private static final File CASE_DIR = new File(caseDirectoryPath.toString());
public static Test suite() {
NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(IngestFileFiltersTest.class).
clusters(".*").
enableModules(".*");
return conf.suite();
}
@Override
public void setUp() {
try {
Case.createAsCurrentCase(Case.CaseType.SINGLE_USER_CASE, caseDirectoryPath.toString(), new CaseDetails("IngestFiltersTest"));
} catch (CaseActionException ex) {
Exceptions.printStackTrace(ex);
}
assertTrue(CASE_DIR.exists());
}
@Override
public void tearDown() {
try {
Case.closeCurrentCase();
FileUtils.deleteDirectory(CASE_DIR);
} catch (CaseActionException | IOException ex) {
Exceptions.printStackTrace(ex);
}
assertFalse(CASE_DIR.exists());
}
public void testFilter() {
System.out.println("testFilter");
}
}

View File

@ -0,0 +1,109 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 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.util.ArrayList;
import java.util.List;
import javax.annotation.concurrent.Immutable;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.datamodel.Content;
/**
* A data source processor "callback" for unit testing that collects the results
* of running a data source processor on a data source and unblocks the job
* processing thread when the data source processor finishes running in its own
* thread.
*/
@Immutable
public class FunctionalTestDspCallback extends DataSourceProcessorCallback {
private final Object monitor;
private final List<String> errorMessages = new ArrayList<>();
private final List<Content> dataSourceContent = new ArrayList<>();
/**
* Constructs a data source processor "callback" for unit testing that
* collects the results of running a data source processor on a data source
* and unblocks the job processing thread when the data source processor
* finishes running in its own thread.
*
* @param monitor A monitor for the callback to signal when the data source
* processor completes its processing.
*/
FunctionalTestDspCallback(Object monitor) {
this.monitor = monitor;
}
/**
* Called by the data source processor when it finishes running in its own
* thread.
*
* @param result The result code for the processing of the data
* source.
* @param errorMessages Any error messages generated during the
* processing of the data source.
* @param dataSourceContent The content produced by processing the data
* source.
*/
@Override
public void done(DataSourceProcessorCallback.DataSourceProcessorResult result, List<String> errorMessages, List<Content> dataSourceContent) {
this.errorMessages.addAll(errorMessages);
this.dataSourceContent.addAll(dataSourceContent);
synchronized (monitor) {
monitor.notify();
}
}
/**
* Called by the data source processor when it finishes running in its own
* thread, if that thread is the AWT (Abstract Window Toolkit) event
* dispatch thread (EDT).
*
* @param result The result code for the processing of the data
* source.
* @param errorMessages Any error messages generated during the
* processing of the data source.
* @param dataSourceContent The content produced by processing the data
* source.
*/
@Override
public void doneEDT(DataSourceProcessorCallback.DataSourceProcessorResult result, List<String> errorMessages, List<Content> dataSourceContent) {
done(result, errorMessages, dataSourceContent);
}
/**
* Gets any error messages emitted by the data source processor.
*
* @return A list of error messages, possibly empty.
*/
public List<String> getDspErrorMessages() {
return new ArrayList<>(this.errorMessages);
}
/**
* Gets any data source content objects produced by the data source
* processor.
*
* @return A list of content objects, possibly empty.
*/
public List<Content> getDataSourceContent() {
return new ArrayList<>(this.dataSourceContent);
}
}

View File

@ -0,0 +1,62 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 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 javax.annotation.concurrent.Immutable;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
/**
* A data source processor progress monitor for unit testing.
*/
@Immutable
public class FunctionalTestDspProgressMonitor implements DataSourceProcessorProgressMonitor {
/**
* Switches the progress indicator to indeterminate mode (the total number
* of work units to be completed is unknown) or determinate mode (the total
* number of work units to be completed is unknown).
*
* @param indeterminate True for indeterminate mode, false for determinate
* mode.
*/
@Override
public void setIndeterminate(final boolean indeterminate) {
}
/**
* Updates the progress indicator with the number of work units completed so
* far when in determinate mode (the total number of work units to be
* completed is known).
*
* @param workUnitsCompleted Number of work units completed so far.
*/
@Override
public void setProgress(final int workUnitsCompleted) {
}
/**
* Updates the progress indicator with a progress message.
*
* @param message The progress message.
*/
@Override
public void setProgressText(final String message) {
}
}

View File

@ -23,9 +23,9 @@ import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
public class IntestFileFiltersTest { public class IngestFileFiltersTest {
public IntestFileFiltersTest() { public IngestFileFiltersTest() {
} }
@BeforeClass @BeforeClass

View File

@ -28,6 +28,7 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.TimeStampUtils;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
/* /*

View File

@ -1,108 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 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.IOException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.logging.Level;
/**
* Utility for creating and checking for the existence of an automated ingest
* alert file. The purpose of the file is to put a marker in the case directory
* when an error or warning occurs in connection with an automated ingest job.
*/
final class AutoIngestAlertFile {
private static final String ERROR_FILE_NAME = "autoingest.alert";
/**
* Checks whether an automated ingest alert file exists in a case directory.
*
* @param caseDirectoryPath The case directory path.
*
* @return True or false.
*/
static boolean exists(Path caseDirectoryPath) {
return caseDirectoryPath.resolve(ERROR_FILE_NAME).toFile().exists();
}
/**
* Creates an automated ingest alert file in a case directory if such a file
* does not already exist.
*
* @param caseDirectoryPath The case directory path.
*
* @return True or false.
*/
static void create(Path caseDirectoryPath) throws AutoIngestAlertFileException {
try {
Files.createFile(caseDirectoryPath.resolve(ERROR_FILE_NAME));
} catch (FileAlreadyExistsException ignored) {
/*
* The file already exists, the exception is not exceptional.
*/
} catch (IOException ex) {
/*
* FileAlreadyExistsException implementation is optional, so check
* for that case.
*/
if (!exists(caseDirectoryPath)) {
throw new AutoIngestAlertFileException(String.format("Error creating automated ingest alert file in %s", caseDirectoryPath), ex);
}
}
}
/**
* Exception thrown when there is a problem creating an alert file.
*/
final static class AutoIngestAlertFileException extends Exception {
private static final long serialVersionUID = 1L;
/**
* Constructs an exception to throw when there is a problem creating an
* alert file.
*
* @param message The exception message.
*/
private AutoIngestAlertFileException(String message) {
super(message);
}
/**
* Constructs an exception to throw when there is a problem creating an
* alert file.
*
* @param message The exception message.
* @param cause The cause of the exception, if it was an exception.
*/
private AutoIngestAlertFileException(String message, Throwable cause) {
super(message, cause);
}
}
/**
* Prevents instantiation of this utility class.
*/
private AutoIngestAlertFile() {
}
}

View File

@ -1,189 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015-2017 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.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Comparator;
import java.util.Date;
import java.util.Objects;
import java.util.logging.Level;
import org.sleuthkit.autopsy.casemodule.CaseMetadata;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* A representation of a case created by automated ingest.
*/
class AutoIngestCase implements Comparable<AutoIngestCase> {
private static final Logger logger = Logger.getLogger(AutoIngestCase.class.getName());
private final Path caseDirectoryPath;
private final String caseName;
private final Path metadataFilePath;
private final Date createDate;
private final Date lastAccessedDate;
/**
* Constructs a representation of case created by automated ingest.
*
* @param caseDirectoryPath The case directory path.
*/
AutoIngestCase(Path caseDirectoryPath) {
this.caseDirectoryPath = caseDirectoryPath;
caseName = PathUtils.caseNameFromCaseDirectoryPath(caseDirectoryPath);
metadataFilePath = caseDirectoryPath.resolve(caseName + CaseMetadata.getFileExtension());
BasicFileAttributes fileAttrs = null;
try {
fileAttrs = Files.readAttributes(metadataFilePath, BasicFileAttributes.class);
} catch (IOException ex) {
logger.log(Level.SEVERE, String.format("Error reading file attributes of case metadata file in %s, will use current time for case createDate/lastModfiedDate", caseDirectoryPath), ex);
}
if (null != fileAttrs) {
createDate = new Date(fileAttrs.creationTime().toMillis());
lastAccessedDate = new Date(fileAttrs.lastAccessTime().toMillis());
} else {
createDate = new Date();
lastAccessedDate = new Date();
}
}
/**
* Gets the case directory path.
*
* @return The case directory path.
*/
Path getCaseDirectoryPath() {
return this.caseDirectoryPath;
}
/**
* Gets the case name.
*
* @return The case name.
*/
String getCaseName() {
return this.caseName;
}
/**
* Gets the creation date for the case, defined as the create time of the
* case metadata file.
*
* @return The case creation date.
*/
Date getCreationDate() {
return this.createDate;
}
/**
* Gets the last accessed date for the case, defined as the last accessed
* time of the case metadata file.
*
* @return The last accessed date.
*/
Date getLastAccessedDate() {
return this.lastAccessedDate;
}
/**
* Gets the status of this case based on the auto ingest result file in the
* case directory.
*
* @return See CaseStatus enum definition.
*/
CaseStatus getStatus() {
if (AutoIngestAlertFile.exists(caseDirectoryPath)) {
return CaseStatus.ALERT;
} else {
return CaseStatus.OK;
}
}
/**
* Indicates whether or not some other object is "equal to" this
* AutoIngestCase object.
*
* @param other The other object.
*
* @return True or false.
*/
@Override
public boolean equals(Object other) {
if (!(other instanceof AutoIngestCase)) {
return false;
}
if (other == this) {
return true;
}
return this.caseDirectoryPath.toString().equals(((AutoIngestCase) other).caseDirectoryPath.toString());
}
/**
* Returns a hash code value for this AutoIngestCase object.
*
* @return The has code.
*/
@Override
public int hashCode() {
int hash = 7;
hash = 71 * hash + Objects.hashCode(this.caseDirectoryPath);
hash = 71 * hash + Objects.hashCode(this.createDate);
hash = 71 * hash + Objects.hashCode(this.caseName);
return hash;
}
/**
* Compares this AutopIngestCase object with abnother AutoIngestCase object
* for order.
*/
@Override
public int compareTo(AutoIngestCase other) {
return -this.lastAccessedDate.compareTo(other.getLastAccessedDate());
}
/**
* Comparator for a descending order sort on date created.
*/
static class LastAccessedDateDescendingComparator implements Comparator<AutoIngestCase> {
/**
* Compares two AutoIngestCase objects for order based on last accessed
* date (descending).
*
* @param object The first AutoIngestCase object
* @param otherObject The second AuotIngestCase object.
*
* @return A negative integer, zero, or a positive integer as the first
* argument is less than, equal to, or greater than the second.
*/
@Override
public int compare(AutoIngestCase object, AutoIngestCase otherObject) {
return -object.getLastAccessedDate().compareTo(otherObject.getLastAccessedDate());
}
}
enum CaseStatus {
OK,
ALERT
}
}

View File

@ -1,162 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 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.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
/**
* Handles locating and opening cases created by auto ingest.
*/
final class AutoIngestCaseManager {
private static AutoIngestCaseManager instance;
private CoordinationService coordinationService;
/**
* Gets the auto ingest case manager.
*
* @return The auto ingest case manager singleton.
*
* @throws AutoIngestCaseManagerException
*/
synchronized static AutoIngestCaseManager getInstance() throws AutoIngestCaseManager.AutoIngestCaseManagerException {
if (null == instance) {
instance = new AutoIngestCaseManager();
}
return instance;
}
/**
* Constructs an object that handles locating and opening cases created by
* auto ingest.
*
* @throws AutoIngestCaseManagerException
*/
private AutoIngestCaseManager() throws AutoIngestCaseManagerException {
try {
coordinationService = CoordinationService.getInstance();
} catch (CoordinationServiceException ex) {
throw new AutoIngestCaseManager.AutoIngestCaseManagerException("Failed to get the coordination service.", ex);
}
}
/**
* Gets a list of the cases in the top level case folder used by auto
* ingest.
*
* @return List of cases.
*
* @throws AutoIngestCaseManagerException
*/
List<AutoIngestCase> getCases() throws AutoIngestCaseManagerException {
List<AutoIngestCase> cases = new ArrayList<>();
List<Path> casePathList = getCasePaths();
for (Path casePath : casePathList) {
cases.add(new AutoIngestCase(casePath));
}
return cases;
}
/**
* Retrieve all of the case nodes and filter for only those that represent
* case paths.
*
* @return List of case paths.
*
* @throws AutoIngestCaseManagerException
*/
private List<Path> getCasePaths() throws AutoIngestCaseManagerException {
try {
List<String> nodeList = coordinationService.getNodeList(CoordinationService.CategoryNode.CASES);
List<Path> casePathList = new ArrayList<Path>(0);
for (String node : nodeList) {
if(node.indexOf('\\') >= 0 || node.indexOf('/') >= 0) {
/*
* This is not a case name lock (name specifies a path).
*/
String nodeUpperCase = node.toUpperCase();
if(!nodeUpperCase.endsWith("_RESOURCES") && !nodeUpperCase.endsWith("AUTO_INGEST_LOG.TXT")) {
/*
* This is not a case resource lock, nor a case auto
* ingest log lock. Collect the path.
*/
casePathList.add(Paths.get(node));
}
}
}
return casePathList;
} catch (CoordinationServiceException ex) {
throw new AutoIngestCaseManager.AutoIngestCaseManagerException("Failed to get node list from coordination service.", ex);
}
}
/**
* Opens an auto ingest case case.
*
* @param caseMetadataFilePath Path to the case metadata file.
*
* @throws CaseActionException
*/
synchronized void openCase(Path caseMetadataFilePath) throws CaseActionException {
/*
* Open the case.
*/
Case.openAsCurrentCase(caseMetadataFilePath.toString());
}
/**
* Exception type thrown when there is an error completing an auto ingest
* case manager operation.
*/
static final class AutoIngestCaseManagerException extends Exception {
private static final long serialVersionUID = 1L;
/**
* Constructs an instance of the exception type thrown when there is an
* error completing an auto ingest case manager operation.
*
* @param message The exception message.
*/
private AutoIngestCaseManagerException(String message) {
super(message);
}
/**
* Constructs an instance of the exception type thrown when there is an
* error completing an auto ingest case manager operation.
*
* @param message The exception message.
* @param cause A Throwable cause for the error.
*/
private AutoIngestCaseManagerException(String message, Throwable cause) {
super(message, cause);
}
}
}

View File

@ -1,99 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 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 java.awt.event.ActionListener;
import java.util.logging.Level;
import org.openide.util.HelpCtx;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.SystemAction;
import org.sleuthkit.autopsy.casemodule.CaseCloseAction;
import org.sleuthkit.autopsy.casemodule.CaseOpenAction;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.StartupWindowProvider;
import org.sleuthkit.autopsy.core.UserPreferences;
final class AutoIngestCaseOpenAction extends CallableSystemAction implements ActionListener {
private static final Logger logger = Logger.getLogger(AutoIngestCaseOpenAction.class.getName());
private static final long serialVersionUID = 1L;
public AutoIngestCaseOpenAction() {
}
@Override
public void actionPerformed(ActionEvent e) {
UserPreferences.SelectedMode mode = UserPreferences.getMode();
switch (mode) {
case REVIEW:
if (Case.isCaseOpen()) {
/*
* In review mode, close the currently open case, if any, and
* then display the review mode cases panel. This can be
* accomplished by invoking CaseCloseAction because it calls
* StartupWindowProvider.getInstance().open() after it closes
* the current case.
*/
SystemAction.get(CaseCloseAction.class).actionPerformed(e);
} else {
// no case is open, so show the startup window
StartupWindowProvider.getInstance().open();
}
break;
case AUTOINGEST:
/*
* New case action is disabled in auto ingest mode.
*/
break;
case STANDALONE:
/**
* In standalone mode, invoke default Autopsy version of CaseOpenAction.
*/
Lookup.getDefault().lookup(CaseOpenAction.class).actionPerformed(e);
break;
default:
logger.log(Level.SEVERE, "Attempting to open case in unsupported mode {0}", mode.toString());
}
}
@Override
public void performAction() {
}
@Override
public String getName() {
return NbBundle.getMessage(AutoIngestCaseOpenAction.class, "CTL_OpenAction");
}
@Override
public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP;
}
}

View File

@ -169,7 +169,6 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.pendingTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.pendingTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="autoResizeMode" type="int" value="4"/>
<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="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"> <Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
<JTableSelectionModel selectionMode="0"/> <JTableSelectionModel selectionMode="0"/>
@ -193,7 +192,6 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.runningTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.runningTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="autoResizeMode" type="int" value="4"/>
<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="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"> <Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
<JTableSelectionModel selectionMode="0"/> <JTableSelectionModel selectionMode="0"/>
@ -217,7 +215,6 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.completedTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.completedTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="autoResizeMode" type="int" value="4"/>
<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="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"> <Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
<JTableSelectionModel selectionMode="0"/> <JTableSelectionModel selectionMode="0"/>

View File

@ -39,7 +39,6 @@ import javax.swing.DefaultListSelectionModel;
import java.awt.Color; import java.awt.Color;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.io.File; import java.io.File;
import java.util.Collections;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.JPanel; import javax.swing.JPanel;
@ -60,10 +59,13 @@ import org.sleuthkit.autopsy.core.ServicesMonitor;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.NetworkUtils; import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotDialog;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestManager.CaseDeletionResult; import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestManager.CaseDeletionResult;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestManager.JobsSnapshot; import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestManager.JobsSnapshot;
import org.sleuthkit.autopsy.guiutils.DurationCellRenderer;
import org.sleuthkit.autopsy.guiutils.LongDateCellRenderer;
import org.sleuthkit.autopsy.guiutils.StatusIconCellRenderer;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotDialog;
/** /**
* A panel for monitoring automated ingest by a cluster, and for controlling * A panel for monitoring automated ingest by a cluster, and for controlling
@ -138,6 +140,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
private static final int GENERIC_COL_MAX_WIDTH = 2000; private static final int GENERIC_COL_MAX_WIDTH = 2000;
private static final int PENDING_TABLE_COL_PREFERRED_WIDTH = 280; private static final int PENDING_TABLE_COL_PREFERRED_WIDTH = 280;
private static final int RUNNING_TABLE_COL_PREFERRED_WIDTH = 175; 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 ACTIVITY_TIME_COL_MIN_WIDTH = 250; private static final int ACTIVITY_TIME_COL_MIN_WIDTH = 250;
private static final int ACTIVITY_TIME_COL_MAX_WIDTH = 450; private static final int ACTIVITY_TIME_COL_MAX_WIDTH = 450;
private static final int TIME_COL_MIN_WIDTH = 30; private static final int TIME_COL_MIN_WIDTH = 30;
@ -177,6 +181,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
* ordinal or a column header string. * ordinal or a column header string.
*/ */
@Messages({ @Messages({
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority=Prioritized",
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.Case=Case", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Case=Case",
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.ImageFolder=Data Source", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ImageFolder=Data Source",
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.HostName=Host Name", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.HostName=Host Name",
@ -203,8 +208,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
STATUS(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Status")), STATUS(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Status")),
CASE_DIRECTORY_PATH(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.CaseFolder")), CASE_DIRECTORY_PATH(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.CaseFolder")),
IS_LOCAL_JOB(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.LocalJob")), IS_LOCAL_JOB(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.LocalJob")),
MANIFEST_FILE_PATH(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ManifestFilePath")); MANIFEST_FILE_PATH(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ManifestFilePath")),
PRIORITY(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority"));
private final String header; private final String header;
private JobsTableModelColumns(String header) { private JobsTableModelColumns(String header) {
@ -227,7 +232,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
STAGE_TIME.getColumnHeader(), STAGE_TIME.getColumnHeader(),
CASE_DIRECTORY_PATH.getColumnHeader(), CASE_DIRECTORY_PATH.getColumnHeader(),
IS_LOCAL_JOB.getColumnHeader(), IS_LOCAL_JOB.getColumnHeader(),
MANIFEST_FILE_PATH.getColumnHeader()}; MANIFEST_FILE_PATH.getColumnHeader(),
PRIORITY.getColumnHeader()};
} }
/** /**
@ -259,32 +265,11 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
manager = AutoIngestManager.getInstance(); manager = AutoIngestManager.getInstance();
pendingTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) { pendingTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0);
private static final long serialVersionUID = 1L;
@Override runningTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0);
public boolean isCellEditable(int row, int column) {
return false;
}
};
runningTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) { completedTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0);
private static final long serialVersionUID = 1L;
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
completedTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) {
private static final long serialVersionUID = 1L;
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
initComponents(); // Generated code. initComponents(); // Generated code.
setServicesStatusMessage(); setServicesStatusMessage();
@ -292,7 +277,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
initRunningJobsTable(); initRunningJobsTable();
initCompletedJobsTable(); initCompletedJobsTable();
initButtons(); initButtons();
completedTable.getRowSorter().toggleSortOrder(JobsTableModelColumns.COMPLETED_TIME.ordinal());
/* /*
* Must set this flag, otherwise pop up menus don't close properly. * Must set this flag, otherwise pop up menus don't close properly.
*/ */
@ -412,10 +397,16 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
column.setPreferredWidth(TIME_COL_PREFERRED_WIDTH); column.setPreferredWidth(TIME_COL_PREFERRED_WIDTH);
column.setWidth(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);
/** /**
* Prevent sorting when a column header is clicked. * Allow sorting when a column header is clicked.
*/ */
pendingTable.setAutoCreateRowSorter(false); pendingTable.setRowSorter(new AutoIngestRowSorter<>(pendingTableModel));
/* /*
* Create a row selection listener to enable/disable the prioritize * Create a row selection listener to enable/disable the prioritize
@ -454,7 +445,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader())); runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.IS_LOCAL_JOB.getColumnHeader())); runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.IS_LOCAL_JOB.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader())); runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader()));
/* /*
* Set up a column to display the cases associated with the jobs. * Set up a column to display the cases associated with the jobs.
*/ */
@ -524,9 +515,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
} }
private void updateRunningTableButtonsBasedOnSelectedRow() { private void updateRunningTableButtonsBasedOnSelectedRow() {
int row = runningTable.getSelectedRow(); int row = runningTable.convertRowIndexToModel(runningTable.getSelectedRow());
if (row >= 0 && row < runningTable.getRowCount()) { if (row >= 0 && row < runningTable.getRowCount()) {
if ((boolean) runningTableModel.getValueAt(row, JobsTableModelColumns.IS_LOCAL_JOB.ordinal())) { if ((boolean) runningTable.getModel().getValueAt(row, JobsTableModelColumns.IS_LOCAL_JOB.ordinal())) {
enableRunningTableButtons(true); enableRunningTableButtons(true);
return; return;
} }
@ -544,13 +535,13 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
* does not remove the columns from the model, just from this table. * 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.STARTED_TIME.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.HOST_NAME.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.STAGE.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.STAGE.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.STAGE_TIME.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.STAGE_TIME.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.IS_LOCAL_JOB.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.IS_LOCAL_JOB.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.HOST_NAME.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader()));
/* /*
* Set up a column to display the cases associated with the jobs. * Set up a column to display the cases associated with the jobs.
*/ */
@ -596,16 +587,16 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
* renderer that will choose an icon to represent the job status. * renderer that will choose an icon to represent the job status.
*/ */
column = completedTable.getColumn(JobsTableModelColumns.STATUS.getColumnHeader()); column = completedTable.getColumn(JobsTableModelColumns.STATUS.getColumnHeader());
column.setCellRenderer(new CaseStatusIconCellRenderer()); column.setCellRenderer(new StatusIconCellRenderer());
column.setMinWidth(STATUS_COL_MIN_WIDTH); column.setMinWidth(STATUS_COL_MIN_WIDTH);
column.setMaxWidth(STATUS_COL_MAX_WIDTH); column.setMaxWidth(STATUS_COL_MAX_WIDTH);
column.setPreferredWidth(STATUS_COL_PREFERRED_WIDTH); column.setPreferredWidth(STATUS_COL_PREFERRED_WIDTH);
column.setWidth(STATUS_COL_PREFERRED_WIDTH); column.setWidth(STATUS_COL_PREFERRED_WIDTH);
/* /*
* Prevent sorting when a column header is clicked. * Allow sorting when a column header is clicked.
*/ */
completedTable.setAutoCreateRowSorter(false); completedTable.setRowSorter(new AutoIngestRowSorter<>(completedTableModel));
/* /*
* Create a row selection listener to enable/disable the delete case and * Create a row selection listener to enable/disable the delete case and
@ -982,7 +973,6 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
List<AutoIngestJob> completedJobs = new ArrayList<>(); List<AutoIngestJob> completedJobs = new ArrayList<>();
manager.getJobs(pendingJobs, runningJobs, completedJobs); manager.getJobs(pendingJobs, runningJobs, completedJobs);
// Sort the completed jobs list by completed date // Sort the completed jobs list by completed date
Collections.sort(completedJobs, new AutoIngestJob.CompletedDateDescendingComparator());
EventQueue.invokeLater(new RefreshComponentsTask(pendingJobs, runningJobs, completedJobs)); EventQueue.invokeLater(new RefreshComponentsTask(pendingJobs, runningJobs, completedJobs));
} }
} }
@ -1030,9 +1020,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
*/ */
if (null != pendingJobs) { if (null != pendingJobs) {
Path currentRow = getSelectedEntry(pendingTable, pendingTableModel); Path currentRow = getSelectedEntry(pendingTable);
refreshTable(pendingJobs, pendingTableModel, null); refreshTable(pendingJobs, (DefaultTableModel) pendingTable.getModel(), null);
setSelectedEntry(pendingTable, pendingTableModel, currentRow); setSelectedEntry(pendingTable, currentRow);
} }
if (null != runningJobs) { if (null != runningJobs) {
@ -1041,15 +1031,15 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
} else { } else {
updateRunningTableButtonsBasedOnSelectedRow(); updateRunningTableButtonsBasedOnSelectedRow();
} }
Path currentRow = getSelectedEntry(runningTable, runningTableModel); Path currentRow = getSelectedEntry(runningTable);
refreshTable(runningJobs, runningTableModel, null); refreshTable(runningJobs, (DefaultTableModel) runningTable.getModel(), null);
setSelectedEntry(runningTable, runningTableModel, currentRow); setSelectedEntry(runningTable, currentRow);
} }
if (null != completedJobs) { if (null != completedJobs) {
Path currentRow = getSelectedEntry(completedTable, completedTableModel); Path currentRow = getSelectedEntry(completedTable);
refreshTable(completedJobs, completedTableModel, null); refreshTable(completedJobs, (DefaultTableModel) completedTable.getModel(), null);
setSelectedEntry(completedTable, completedTableModel, currentRow); setSelectedEntry(completedTable, currentRow);
} }
} }
@ -1087,12 +1077,12 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
* *
* @return a path representing the current selection * @return a path representing the current selection
*/ */
Path getSelectedEntry(JTable table, DefaultTableModel tableModel) { Path getSelectedEntry(JTable table) {
try { try {
int currentlySelectedRow = table.getSelectedRow(); int currentlySelectedRow = table.convertRowIndexToModel(table.getSelectedRow());
if (currentlySelectedRow >= 0 && currentlySelectedRow < table.getRowCount()) { if (currentlySelectedRow >= 0 && currentlySelectedRow < table.getRowCount()) {
return Paths.get(tableModel.getValueAt(currentlySelectedRow, JobsTableModelColumns.CASE.ordinal()).toString(), return Paths.get(table.getModel().getValueAt(currentlySelectedRow, JobsTableModelColumns.CASE.ordinal()).toString(),
tableModel.getValueAt(currentlySelectedRow, JobsTableModelColumns.DATA_SOURCE.ordinal()).toString()); table.getModel().getValueAt(currentlySelectedRow, JobsTableModelColumns.DATA_SOURCE.ordinal()).toString());
} }
} catch (Exception ignored) { } catch (Exception ignored) {
return null; return null;
@ -1108,12 +1098,12 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
* @param tableModel The tableModel of the table to set * @param tableModel The tableModel of the table to set
* @param path The path of the item to set * @param path The path of the item to set
*/ */
void setSelectedEntry(JTable table, DefaultTableModel tableModel, Path path) { void setSelectedEntry(JTable table, Path path) {
if (path != null) { if (path != null) {
try { try {
for (int row = 0; row < table.getRowCount(); ++row) { for (int row = 0; row < table.getRowCount(); ++row) {
Path temp = Paths.get(tableModel.getValueAt(row, JobsTableModelColumns.CASE.ordinal()).toString(), Path temp = Paths.get(table.getModel().getValueAt(row, JobsTableModelColumns.CASE.ordinal()).toString(),
tableModel.getValueAt(row, JobsTableModelColumns.DATA_SOURCE.ordinal()).toString()); table.getModel().getValueAt(row, JobsTableModelColumns.DATA_SOURCE.ordinal()).toString());
if (temp.compareTo(path) == 0) { // found it if (temp.compareTo(path) == 0) { // found it
table.setRowSelectionInterval(row, row); table.setRowSelectionInterval(row, row);
return; return;
@ -1152,11 +1142,12 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
job.getProcessingStageStartDate(), // STARTED_TIME job.getProcessingStageStartDate(), // STARTED_TIME
job.getCompletedDate(), // COMPLETED_TIME job.getCompletedDate(), // COMPLETED_TIME
status.getDescription(), // ACTIVITY status.getDescription(), // ACTIVITY
job.getErrorsOccurred(), // STATUS job.getErrorsOccurred() ? StatusIconCellRenderer.Status.WARNING : StatusIconCellRenderer.Status.OK, // STATUS
((Date.from(Instant.now()).getTime()) - (status.getStartDate().getTime())), // ACTIVITY_TIME ((Date.from(Instant.now()).getTime()) - (status.getStartDate().getTime())), // ACTIVITY_TIME
job.getCaseDirectoryPath(), // CASE_DIRECTORY_PATH job.getCaseDirectoryPath(), // CASE_DIRECTORY_PATH
job.getProcessingHostName().equals(LOCAL_HOST_NAME), // IS_LOCAL_JOB job.getProcessingHostName().equals(LOCAL_HOST_NAME), // IS_LOCAL_JOB
job.getManifest().getFilePath()}); // MANIFEST_FILE_PATH job.getManifest().getFilePath(), // MANIFEST_FILE_PATH
job.getPriority()}); // PRIORITY
} }
} catch (Exception ex) { } catch (Exception ex) {
SYS_LOGGER.log(Level.SEVERE, "Dashboard error refreshing table", ex); SYS_LOGGER.log(Level.SEVERE, "Dashboard error refreshing table", ex);
@ -1168,9 +1159,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
*/ */
private void refreshTables() { private void refreshTables() {
JobsSnapshot jobsSnapshot = manager.getCurrentJobsSnapshot(); JobsSnapshot jobsSnapshot = manager.getCurrentJobsSnapshot();
refreshTable(jobsSnapshot.getCompletedJobs(), completedTableModel, null); refreshTable(jobsSnapshot.getCompletedJobs(), (DefaultTableModel) completedTable.getModel(), null);
refreshTable(jobsSnapshot.getPendingJobs(), pendingTableModel, null); refreshTable(jobsSnapshot.getPendingJobs(), (DefaultTableModel) pendingTable.getModel(), null);
refreshTable(jobsSnapshot.getRunningJobs(), runningTableModel, null); refreshTable(jobsSnapshot.getRunningJobs(), (DefaultTableModel) runningTable.getModel(), null);
} }
/** /**
@ -1211,7 +1202,6 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
pendingTable.setModel(pendingTableModel); pendingTable.setModel(pendingTableModel);
pendingTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.pendingTable.toolTipText")); // NOI18N pendingTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.pendingTable.toolTipText")); // NOI18N
pendingTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
pendingTable.setRowHeight(20); pendingTable.setRowHeight(20);
pendingTable.setSelectionModel(new DefaultListSelectionModel() { pendingTable.setSelectionModel(new DefaultListSelectionModel() {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -1229,7 +1219,6 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
runningTable.setModel(runningTableModel); runningTable.setModel(runningTableModel);
runningTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.runningTable.toolTipText")); // NOI18N runningTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.runningTable.toolTipText")); // NOI18N
runningTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
runningTable.setRowHeight(20); runningTable.setRowHeight(20);
runningTable.setSelectionModel(new DefaultListSelectionModel() { runningTable.setSelectionModel(new DefaultListSelectionModel() {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -1247,7 +1236,6 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
completedTable.setModel(completedTableModel); completedTable.setModel(completedTableModel);
completedTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.completedTable.toolTipText")); // NOI18N completedTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.completedTable.toolTipText")); // NOI18N
completedTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
completedTable.setRowHeight(20); completedTable.setRowHeight(20);
completedTable.setSelectionModel(new DefaultListSelectionModel() { completedTable.setSelectionModel(new DefaultListSelectionModel() {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -1425,10 +1413,10 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
.addComponent(completedScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 920, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(completedScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 920, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(bnCancelJob, javax.swing.GroupLayout.DEFAULT_SIZE, 117, Short.MAX_VALUE) .addComponent(bnCancelJob, javax.swing.GroupLayout.PREFERRED_SIZE, 117, Short.MAX_VALUE)
.addComponent(bnShowProgress, javax.swing.GroupLayout.DEFAULT_SIZE, 116, Short.MAX_VALUE) .addComponent(bnShowProgress, javax.swing.GroupLayout.PREFERRED_SIZE, 116, Short.MAX_VALUE)
.addComponent(bnCancelModule, javax.swing.GroupLayout.DEFAULT_SIZE, 117, Short.MAX_VALUE) .addComponent(bnCancelModule, javax.swing.GroupLayout.PREFERRED_SIZE, 117, Short.MAX_VALUE)
.addComponent(bnDeleteCase, javax.swing.GroupLayout.DEFAULT_SIZE, 117, Short.MAX_VALUE) .addComponent(bnDeleteCase, javax.swing.GroupLayout.PREFERRED_SIZE, 117, Short.MAX_VALUE)
.addComponent(bnShowCaseLog, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(bnShowCaseLog, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(bnReprocessJob, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) .addComponent(bnReprocessJob, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
@ -1535,11 +1523,11 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
"AutoIngestControlPanel.DeletionFailed=Deletion failed for job" "AutoIngestControlPanel.DeletionFailed=Deletion failed for job"
}) })
private void bnDeleteCaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnDeleteCaseActionPerformed private void bnDeleteCaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnDeleteCaseActionPerformed
if (completedTableModel.getRowCount() < 0 || completedTable.getSelectedRow() < 0) { if (completedTable.getModel().getRowCount() < 0 || completedTable.getSelectedRow() < 0) {
return; return;
} }
String caseName = (String) completedTable.getValueAt(completedTable.getSelectedRow(), JobsTableModelColumns.CASE.ordinal()); String caseName = (String) completedTable.getModel().getValueAt(completedTable.convertRowIndexToModel(completedTable.getSelectedRow()), JobsTableModelColumns.CASE.ordinal());
Object[] options = { Object[] options = {
org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "ConfirmationDialog.Delete"), org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "ConfirmationDialog.Delete"),
org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "ConfirmationDialog.DoNotDelete") org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "ConfirmationDialog.DoNotDelete")
@ -1556,8 +1544,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
if (reply == JOptionPane.YES_OPTION) { if (reply == JOptionPane.YES_OPTION) {
bnDeleteCase.setEnabled(false); bnDeleteCase.setEnabled(false);
bnShowCaseLog.setEnabled(false); bnShowCaseLog.setEnabled(false);
if (completedTableModel.getRowCount() > 0 && completedTable.getSelectedRow() >= 0) { if (completedTable.getModel().getRowCount() > 0 && completedTable.getSelectedRow() >= 0) {
Path caseDirectoryPath = (Path) completedTableModel.getValueAt(completedTable.getSelectedRow(), JobsTableModelColumns.CASE_DIRECTORY_PATH.ordinal()); Path caseDirectoryPath = (Path) completedTable.getModel().getValueAt(completedTable.convertRowIndexToModel(completedTable.getSelectedRow()), JobsTableModelColumns.CASE_DIRECTORY_PATH.ordinal());
completedTable.clearSelection(); completedTable.clearSelection();
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
CaseDeletionResult result = manager.deleteCase(caseName, caseDirectoryPath); CaseDeletionResult result = manager.deleteCase(caseName, caseDirectoryPath);
@ -1703,9 +1691,10 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
*/ */
@Messages({"AutoIngestControlPanel.casePrioritization.errorMessage=An error occurred when prioritizing the case. Some or all jobs may not have been prioritized."}) @Messages({"AutoIngestControlPanel.casePrioritization.errorMessage=An error occurred when prioritizing the case. Some or all jobs may not have been prioritized."})
private void bnPrioritizeCaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnPrioritizeCaseActionPerformed private void bnPrioritizeCaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnPrioritizeCaseActionPerformed
if (pendingTableModel.getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) { if (pendingTable.getModel().getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) {
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
String caseName = (pendingTableModel.getValueAt(pendingTable.getSelectedRow(), JobsTableModelColumns.CASE.ordinal())).toString();
String caseName = (pendingTable.getModel().getValueAt(pendingTable.convertRowIndexToModel(pendingTable.getSelectedRow()), JobsTableModelColumns.CASE.ordinal())).toString();
try { try {
manager.prioritizeCase(caseName); manager.prioritizeCase(caseName);
} catch (AutoIngestManager.AutoIngestManagerException ex) { } catch (AutoIngestManager.AutoIngestManagerException ex) {
@ -1731,9 +1720,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
}) })
private void bnShowCaseLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnShowCaseLogActionPerformed private void bnShowCaseLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnShowCaseLogActionPerformed
try { try {
int selectedRow = completedTable.getSelectedRow(); int selectedRow = completedTable.convertRowIndexToModel(completedTable.getSelectedRow());
if (selectedRow != -1) { if (selectedRow != -1) {
Path caseDirectoryPath = (Path) completedTableModel.getValueAt(selectedRow, JobsTableModelColumns.CASE_DIRECTORY_PATH.ordinal()); Path caseDirectoryPath = (Path) completedTable.getModel().getValueAt(selectedRow, JobsTableModelColumns.CASE_DIRECTORY_PATH.ordinal());
if (null != caseDirectoryPath) { if (null != caseDirectoryPath) {
Path pathToLog = AutoIngestJobLogger.getLogPath(caseDirectoryPath); Path pathToLog = AutoIngestJobLogger.getLogPath(caseDirectoryPath);
if (pathToLog.toFile().exists()) { if (pathToLog.toFile().exists()) {
@ -1762,9 +1751,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
@Messages({"AutoIngestControlPanel.jobPrioritization.errorMessage=An error occurred when prioritizing the job."}) @Messages({"AutoIngestControlPanel.jobPrioritization.errorMessage=An error occurred when prioritizing the job."})
private void bnPrioritizeJobActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnPrioritizeJobActionPerformed private void bnPrioritizeJobActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnPrioritizeJobActionPerformed
if (pendingTableModel.getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) { if (pendingTable.getModel().getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) {
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
Path manifestFilePath = (Path) (pendingTableModel.getValueAt(pendingTable.getSelectedRow(), JobsTableModelColumns.MANIFEST_FILE_PATH.ordinal())); Path manifestFilePath = (Path) (pendingTable.getModel().getValueAt(pendingTable.convertRowIndexToModel(pendingTable.getSelectedRow()), JobsTableModelColumns.MANIFEST_FILE_PATH.ordinal()));
try { try {
manager.prioritizeJob(manifestFilePath); manager.prioritizeJob(manifestFilePath);
} catch (AutoIngestManager.AutoIngestManagerException ex) { } catch (AutoIngestManager.AutoIngestManagerException ex) {
@ -1791,11 +1780,11 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
}//GEN-LAST:event_bnOpenLogDirActionPerformed }//GEN-LAST:event_bnOpenLogDirActionPerformed
private void bnReprocessJobActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnReprocessJobActionPerformed private void bnReprocessJobActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnReprocessJobActionPerformed
if (completedTableModel.getRowCount() < 0 || completedTable.getSelectedRow() < 0) { if (completedTable.getModel().getRowCount() < 0 || completedTable.getSelectedRow() < 0) {
return; return;
} }
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
Path manifestPath = (Path) completedTableModel.getValueAt(completedTable.getSelectedRow(), JobsTableModelColumns.MANIFEST_FILE_PATH.ordinal()); Path manifestPath = (Path) completedTable.getModel().getValueAt(completedTable.convertRowIndexToModel(completedTable.getSelectedRow()), JobsTableModelColumns.MANIFEST_FILE_PATH.ordinal());
manager.reprocessJob(manifestPath); manager.reprocessJob(manifestPath);
refreshTables(); refreshTables();
AutoIngestControlPanel.this.setCursor(Cursor.getDefaultCursor()); AutoIngestControlPanel.this.setCursor(Cursor.getDefaultCursor());
@ -1830,4 +1819,33 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
private javax.swing.JTextField tbStatusMessage; private javax.swing.JTextField tbStatusMessage;
// End of variables declaration//GEN-END:variables // 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

@ -29,8 +29,19 @@
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0"> <Group type="103" groupAlignment="1" attributes="0">
<Component id="pendingScrollPane" max="32767" 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"> <Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="1" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="refreshButton" min="-2" pref="100" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="prioritizeJobButton" min="-2" pref="100" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="prioritizeCaseButton" min="-2" pref="100" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="clusterMetricsButton" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="lbPending" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="lbPending" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lbCompleted" 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"/> <Component id="lbRunning" alignment="0" min="-2" max="-2" attributes="0"/>
@ -39,18 +50,9 @@
<EmptySpace type="unrelated" max="-2" attributes="0"/> <EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="tbServicesStatusMessage" min="-2" pref="861" max="-2" attributes="0"/> <Component id="tbServicesStatusMessage" min="-2" pref="861" max="-2" attributes="0"/>
</Group> </Group>
<Group type="102" alignment="0" attributes="0">
<Component id="refreshButton" min="-2" pref="100" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="prioritizeJobButton" min="-2" pref="100" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="prioritizeCaseButton" min="-2" pref="100" max="-2" attributes="0"/>
</Group>
</Group> </Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/> <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group> </Group>
<Component id="runningScrollPane" alignment="0" max="32767" attributes="0"/>
<Component id="completedScrollPane" alignment="0" max="32767" attributes="0"/>
</Group> </Group>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
</Group> </Group>
@ -81,6 +83,7 @@
<Component id="refreshButton" alignment="3" min="-2" max="-2" 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="prioritizeJobButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="prioritizeCaseButton" 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"/>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
</Group> </Group>
@ -103,7 +106,6 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <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;)"/> <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>
<Property name="autoResizeMode" type="int" value="4"/>
<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="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"> <Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
<JTableSelectionModel selectionMode="0"/> <JTableSelectionModel selectionMode="0"/>
@ -127,7 +129,6 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <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;)"/> <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>
<Property name="autoResizeMode" type="int" value="4"/>
<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="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"> <Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
<JTableSelectionModel selectionMode="0"/> <JTableSelectionModel selectionMode="0"/>
@ -151,7 +152,6 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <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;)"/> <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>
<Property name="autoResizeMode" type="int" value="4"/>
<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="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"> <Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
<JTableSelectionModel selectionMode="0"/> <JTableSelectionModel selectionMode="0"/>
@ -255,5 +255,15 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="prioritizeCaseButtonActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="prioritizeCaseButtonActionPerformed"/>
</Events> </Events>
</Component> </Component>
<Component class="javax.swing.JButton" name="clusterMetricsButton">
<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.clusterMetricsButton.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="clusterMetricsButtonActionPerformed"/>
</Events>
</Component>
</SubComponents> </SubComponents>
</Form> </Form>

View File

@ -44,17 +44,22 @@ import org.sleuthkit.autopsy.core.ServicesMonitor;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestMonitor.JobsSnapshot; 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. * A dashboard for monitoring an automated ingest cluster.
*/ */
public final class AutoIngestDashboard extends JPanel implements Observer { final class AutoIngestDashboard extends JPanel implements Observer {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final int GENERIC_COL_MIN_WIDTH = 30; private static final int GENERIC_COL_MIN_WIDTH = 30;
private static final int GENERIC_COL_MAX_WIDTH = 2000; private static final int GENERIC_COL_MAX_WIDTH = 2000;
private static final int PENDING_TABLE_COL_PREFERRED_WIDTH = 280; private static final int PENDING_TABLE_COL_PREFERRED_WIDTH = 280;
private static final int RUNNING_TABLE_COL_PREFERRED_WIDTH = 175; 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_MIN_WIDTH = 250;
private static final int STAGE_TIME_COL_MAX_WIDTH = 450; 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_MIN_WIDTH = 30;
@ -100,32 +105,11 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
* Constructs a panel for monitoring an automated ingest cluster. * Constructs a panel for monitoring an automated ingest cluster.
*/ */
private AutoIngestDashboard() { private AutoIngestDashboard() {
pendingTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) { pendingTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0);
private static final long serialVersionUID = 1L;
@Override runningTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0);
public boolean isCellEditable(int row, int column) {
return false;
}
};
runningTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) { completedTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0);
private static final long serialVersionUID = 1L;
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
completedTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) {
private static final long serialVersionUID = 1L;
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
initComponents(); initComponents();
setServicesStatusMessage(); setServicesStatusMessage();
@ -243,10 +227,15 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
column.setPreferredWidth(TIME_COL_PREFERRED_WIDTH); column.setPreferredWidth(TIME_COL_PREFERRED_WIDTH);
column.setWidth(TIME_COL_PREFERRED_WIDTH); column.setWidth(TIME_COL_PREFERRED_WIDTH);
/** column = pendingTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader());
* Prevent sorting when a column header is clicked. 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.setAutoCreateRowSorter(false); pendingTable.setRowSorter(new AutoIngestRowSorter<>(pendingTableModel));
/* /*
* Create a row selection listener to enable/disable the Prioritize * Create a row selection listener to enable/disable the Prioritize
@ -258,7 +247,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
} }
int row = pendingTable.getSelectedRow(); int row = pendingTable.getSelectedRow();
boolean enablePrioritizeButtons = (row >= 0 && row < pendingTable.getRowCount()); boolean enablePrioritizeButtons = (row >= 0 && row < pendingTable.getRowCount());
this.prioritizeJobButton.setEnabled(enablePrioritizeButtons); this.prioritizeJobButton.setEnabled(enablePrioritizeButtons);
this.prioritizeCaseButton.setEnabled(enablePrioritizeButtons); this.prioritizeCaseButton.setEnabled(enablePrioritizeButtons);
}); });
@ -280,7 +269,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader())); runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader())); runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.JOB.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. * Set up a column to display the cases associated with the jobs.
*/ */
@ -354,7 +343,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.JOB.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. * Set up a column to display the cases associated with the jobs.
*/ */
@ -400,16 +389,15 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
* renderer that will choose an icon to represent the job status. * renderer that will choose an icon to represent the job status.
*/ */
column = completedTable.getColumn(JobsTableModelColumns.STATUS.getColumnHeader()); column = completedTable.getColumn(JobsTableModelColumns.STATUS.getColumnHeader());
column.setCellRenderer(new CaseStatusIconCellRenderer()); column.setCellRenderer(new StatusIconCellRenderer());
column.setMinWidth(STATUS_COL_MIN_WIDTH); column.setMinWidth(STATUS_COL_MIN_WIDTH);
column.setMaxWidth(STATUS_COL_MAX_WIDTH); column.setMaxWidth(STATUS_COL_MAX_WIDTH);
column.setPreferredWidth(STATUS_COL_PREFERRED_WIDTH); column.setPreferredWidth(STATUS_COL_PREFERRED_WIDTH);
column.setWidth(STATUS_COL_PREFERRED_WIDTH); column.setWidth(STATUS_COL_PREFERRED_WIDTH);
/* /*
* Prevent sorting when a column header is clicked. * Allow sorting when a column header is clicked.
*/ */
completedTable.setAutoCreateRowSorter(false); completedTable.setRowSorter(new AutoIngestRowSorter<>(completedTableModel));
} }
/** /**
@ -472,10 +460,11 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
job.getProcessingStageStartDate(), // STARTED_TIME job.getProcessingStageStartDate(), // STARTED_TIME
job.getCompletedDate(), // COMPLETED_TIME job.getCompletedDate(), // COMPLETED_TIME
status.getDescription(), // STAGE status.getDescription(), // STAGE
job.getErrorsOccurred(), // STATUS job.getErrorsOccurred() ? StatusIconCellRenderer.Status.WARNING : StatusIconCellRenderer.Status.OK, // STATUS
((Date.from(Instant.now()).getTime()) - (status.getStartDate().getTime())), // STAGE_TIME ((Date.from(Instant.now()).getTime()) - (status.getStartDate().getTime())), // STAGE_TIME
job.getCaseDirectoryPath(), // CASE_DIRECTORY_PATH job.getCaseDirectoryPath(), // CASE_DIRECTORY_PATH
job.getManifest().getFilePath(), // MANIFEST_FILE_PATH job.getManifest().getFilePath(), // MANIFEST_FILE_PATH
job.getPriority(), // PRIORITY
job job
}); });
} }
@ -541,6 +530,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
* described by either an enum ordinal or a column header string. * described by either an enum ordinal or a column header string.
*/ */
private enum JobsTableModelColumns { private enum JobsTableModelColumns {
@Messages({"AutoIngestDashboard.JobsTableModel.ColumnHeader.Priority=Prioritized"})
CASE(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Case")), CASE(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Case")),
DATA_SOURCE(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.ImageFolder")), DATA_SOURCE(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.ImageFolder")),
@ -553,6 +543,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
STATUS(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Status")), STATUS(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Status")),
CASE_DIRECTORY_PATH(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.CaseFolder")), CASE_DIRECTORY_PATH(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.CaseFolder")),
MANIFEST_FILE_PATH(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.ManifestFilePath")), 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")); JOB(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Job"));
private final String header; private final String header;
@ -577,6 +568,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
STAGE_TIME.getColumnHeader(), STAGE_TIME.getColumnHeader(),
CASE_DIRECTORY_PATH.getColumnHeader(), CASE_DIRECTORY_PATH.getColumnHeader(),
MANIFEST_FILE_PATH.getColumnHeader(), MANIFEST_FILE_PATH.getColumnHeader(),
PRIORITY.getColumnHeader(),
JOB.getColumnHeader() JOB.getColumnHeader()
}; };
}; };
@ -662,12 +654,12 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
tbServicesStatusMessage = new javax.swing.JTextField(); tbServicesStatusMessage = new javax.swing.JTextField();
prioritizeJobButton = new javax.swing.JButton(); prioritizeJobButton = new javax.swing.JButton();
prioritizeCaseButton = new javax.swing.JButton(); prioritizeCaseButton = new javax.swing.JButton();
clusterMetricsButton = new javax.swing.JButton();
org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.jButton1.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.jButton1.text")); // NOI18N
pendingTable.setModel(pendingTableModel); pendingTable.setModel(pendingTableModel);
pendingTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.pendingTable.toolTipText")); // NOI18N pendingTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.pendingTable.toolTipText")); // NOI18N
pendingTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
pendingTable.setRowHeight(20); pendingTable.setRowHeight(20);
pendingTable.setSelectionModel(new DefaultListSelectionModel() { pendingTable.setSelectionModel(new DefaultListSelectionModel() {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -685,7 +677,6 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
runningTable.setModel(runningTableModel); runningTable.setModel(runningTableModel);
runningTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.runningTable.toolTipText")); // NOI18N runningTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.runningTable.toolTipText")); // NOI18N
runningTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
runningTable.setRowHeight(20); runningTable.setRowHeight(20);
runningTable.setSelectionModel(new DefaultListSelectionModel() { runningTable.setSelectionModel(new DefaultListSelectionModel() {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -703,7 +694,6 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
completedTable.setModel(completedTableModel); completedTable.setModel(completedTableModel);
completedTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.completedTable.toolTipText")); // NOI18N completedTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.completedTable.toolTipText")); // NOI18N
completedTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
completedTable.setRowHeight(20); completedTable.setRowHeight(20);
completedTable.setSelectionModel(new DefaultListSelectionModel() { completedTable.setSelectionModel(new DefaultListSelectionModel() {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -762,6 +752,13 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
} }
}); });
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) {
clusterMetricsButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
@ -770,24 +767,26 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
.addContainerGap() .addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(pendingScrollPane) .addComponent(pendingScrollPane)
.addComponent(runningScrollPane, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(completedScrollPane, javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(lbPending) .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(lbCompleted)
.addComponent(lbRunning)
.addGroup(layout.createSequentialGroup()
.addComponent(lbServicesStatus)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(tbServicesStatusMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 861, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addComponent(refreshButton, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(refreshButton, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(prioritizeJobButton, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(prioritizeJobButton, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(prioritizeCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE))) .addComponent(prioritizeCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(runningScrollPane, javax.swing.GroupLayout.Alignment.LEADING) .addComponent(clusterMetricsButton))
.addComponent(completedScrollPane, javax.swing.GroupLayout.Alignment.LEADING)) .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)))
.addContainerGap()) .addContainerGap())
); );
layout.setVerticalGroup( layout.setVerticalGroup(
@ -813,7 +812,8 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(refreshButton) .addComponent(refreshButton)
.addComponent(prioritizeJobButton) .addComponent(prioritizeJobButton)
.addComponent(prioritizeCaseButton)) .addComponent(prioritizeCaseButton)
.addComponent(clusterMetricsButton))
.addContainerGap()) .addContainerGap())
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
@ -872,7 +872,12 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
} }
}//GEN-LAST:event_prioritizeCaseButtonActionPerformed }//GEN-LAST:event_prioritizeCaseButtonActionPerformed
private void clusterMetricsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_clusterMetricsButtonActionPerformed
new AutoIngestMetricsDialog(this.getTopLevelAncestor(), autoIngestMonitor);
}//GEN-LAST:event_clusterMetricsButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton clusterMetricsButton;
private javax.swing.JScrollPane completedScrollPane; private javax.swing.JScrollPane completedScrollPane;
private javax.swing.JTable completedTable; private javax.swing.JTable completedTable;
private javax.swing.JButton jButton1; private javax.swing.JButton jButton1;
@ -890,4 +895,33 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
private javax.swing.JTextField tbServicesStatusMessage; private javax.swing.JTextField tbServicesStatusMessage;
// End of variables declaration//GEN-END:variables // 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,7 +25,6 @@ import org.openide.util.HelpCtx;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.openide.util.actions.CallableSystemAction; import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.core.UserPreferences;
import static org.sleuthkit.autopsy.core.UserPreferences.SelectedMode.REVIEW;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
@ActionID(category = "Tools", id = "org.sleuthkit.autopsy.experimental.autoingest.AutoIngestDashboardOpenAction") @ActionID(category = "Tools", id = "org.sleuthkit.autopsy.experimental.autoingest.AutoIngestDashboardOpenAction")
@ -39,8 +38,7 @@ public final class AutoIngestDashboardOpenAction extends CallableSystemAction {
@Override @Override
public boolean isEnabled() { public boolean isEnabled() {
UserPreferences.SelectedMode mode = UserPreferences.getMode(); return (UserPreferences.getIsMultiUserModeEnabled());
return (mode == REVIEW);
} }
@Override @Override

View File

@ -62,7 +62,9 @@ import org.openide.util.Lookup;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.Case.CaseType; import org.sleuthkit.autopsy.casemodule.Case.CaseType;
import org.sleuthkit.autopsy.casemodule.CaseActionException; import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.casemodule.CaseDetails;
import org.sleuthkit.autopsy.casemodule.CaseMetadata; import org.sleuthkit.autopsy.casemodule.CaseMetadata;
import org.sleuthkit.autopsy.coordinationservice.CaseNodeData;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.Lock; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.Lock;
@ -77,7 +79,6 @@ import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import org.sleuthkit.autopsy.events.AutopsyEvent; import org.sleuthkit.autopsy.events.AutopsyEvent;
import org.sleuthkit.autopsy.events.AutopsyEventException; import org.sleuthkit.autopsy.events.AutopsyEventException;
import org.sleuthkit.autopsy.events.AutopsyEventPublisher; import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestAlertFile.AutoIngestAlertFileException;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobLogger.AutoIngestJobLoggerException; import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobLogger.AutoIngestJobLoggerException;
import org.sleuthkit.autopsy.experimental.autoingest.FileExporter.FileExportException; import org.sleuthkit.autopsy.experimental.autoingest.FileExporter.FileExportException;
import org.sleuthkit.autopsy.experimental.autoingest.ManifestFileParser.ManifestFileParserException; import org.sleuthkit.autopsy.experimental.autoingest.ManifestFileParser.ManifestFileParserException;
@ -112,12 +113,11 @@ import org.sleuthkit.autopsy.ingest.IngestModuleError;
* The activities of the auto ingest nodes in a cluster are coordinated by way * The activities of the auto ingest nodes in a cluster are coordinated by way
* of a coordination service and the nodes communicate via event messages. * of a coordination service and the nodes communicate via event messages.
*/ */
public final class AutoIngestManager extends Observable implements PropertyChangeListener { final class AutoIngestManager extends Observable implements PropertyChangeListener {
private static final int NUM_INPUT_SCAN_SCHEDULING_THREADS = 1; private static final int NUM_INPUT_SCAN_SCHEDULING_THREADS = 1;
private static final String INPUT_SCAN_SCHEDULER_THREAD_NAME = "AIM-input-scan-scheduler-%d"; private static final String INPUT_SCAN_SCHEDULER_THREAD_NAME = "AIM-input-scan-scheduler-%d";
private static final String INPUT_SCAN_THREAD_NAME = "AIM-input-scan-%d"; private static final String INPUT_SCAN_THREAD_NAME = "AIM-input-scan-%d";
private static int DEFAULT_JOB_PRIORITY = 0;
private static final String AUTO_INGEST_THREAD_NAME = "AIM-job-processing-%d"; private static final String AUTO_INGEST_THREAD_NAME = "AIM-job-processing-%d";
private static final String LOCAL_HOST_NAME = NetworkUtils.getLocalHostName(); private static final String LOCAL_HOST_NAME = NetworkUtils.getLocalHostName();
private static final String EVENT_CHANNEL_NAME = "Auto-Ingest-Manager-Events"; private static final String EVENT_CHANNEL_NAME = "Auto-Ingest-Manager-Events";
@ -498,6 +498,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} }
SYS_LOGGER.log(Level.INFO, "Starting input scan of {0}", rootInputDirectory); SYS_LOGGER.log(Level.INFO, "Starting input scan of {0}", rootInputDirectory);
InputDirScanner scanner = new InputDirScanner(); InputDirScanner scanner = new InputDirScanner();
scanner.scan(); scanner.scan();
SYS_LOGGER.log(Level.INFO, "Completed input scan of {0}", rootInputDirectory); SYS_LOGGER.log(Level.INFO, "Completed input scan of {0}", rootInputDirectory);
} }
@ -553,10 +554,12 @@ public final class AutoIngestManager extends Observable implements PropertyChang
if (!prioritizedJobs.isEmpty()) { if (!prioritizedJobs.isEmpty()) {
++maxPriority; ++maxPriority;
for (AutoIngestJob job : prioritizedJobs) { for (AutoIngestJob job : prioritizedJobs) {
int oldPriority = job.getPriority();
job.setPriority(maxPriority);
try { try {
this.updateCoordinationServiceNode(job); this.updateCoordinationServiceManifestNode(job);
job.setPriority(maxPriority);
} catch (CoordinationServiceException | InterruptedException ex) { } catch (CoordinationServiceException | InterruptedException ex) {
job.setPriority(oldPriority);
throw new AutoIngestManagerException("Error updating case priority", ex); throw new AutoIngestManagerException("Error updating case priority", ex);
} }
} }
@ -602,17 +605,19 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} }
/* /*
* Bump the priority by one and update the coordination service node * Bump the priority by one and update the coordination service
* data for the job. * manifest node data for the job.
*/ */
if (null != prioritizedJob) { if (null != prioritizedJob) {
++maxPriority; ++maxPriority;
int oldPriority = prioritizedJob.getPriority();
prioritizedJob.setPriority(maxPriority);
try { try {
this.updateCoordinationServiceNode(prioritizedJob); this.updateCoordinationServiceManifestNode(prioritizedJob);
} catch (CoordinationServiceException | InterruptedException ex) { } catch (CoordinationServiceException | InterruptedException ex) {
prioritizedJob.setPriority(oldPriority);
throw new AutoIngestManagerException("Error updating job priority", ex); throw new AutoIngestManagerException("Error updating job priority", ex);
} }
prioritizedJob.setPriority(maxPriority);
} }
Collections.sort(pendingJobs, new AutoIngestJob.PriorityComparator()); Collections.sort(pendingJobs, new AutoIngestJob.PriorityComparator());
@ -649,7 +654,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
/* /*
* Add the job to the pending jobs queue and update the coordination * Add the job to the pending jobs queue and update the coordination
* service node data for the job. * service manifest node data for the job.
*/ */
if (null != completedJob && !completedJob.getCaseDirectoryPath().toString().isEmpty()) { if (null != completedJob && !completedJob.getCaseDirectoryPath().toString().isEmpty()) {
try { try {
@ -661,7 +666,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
completedJob.setCompletedDate(new Date(0)); completedJob.setCompletedDate(new Date(0));
completedJob.setProcessingStatus(PENDING); completedJob.setProcessingStatus(PENDING);
completedJob.setProcessingStage(AutoIngestJob.Stage.PENDING, Date.from(Instant.now())); completedJob.setProcessingStage(AutoIngestJob.Stage.PENDING, Date.from(Instant.now()));
updateCoordinationServiceNode(completedJob); updateCoordinationServiceManifestNode(completedJob);
pendingJobs.add(completedJob); pendingJobs.add(completedJob);
} catch (CoordinationServiceException ex) { } catch (CoordinationServiceException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Coordination service error while reprocessing %s", manifestPath), ex); SYS_LOGGER.log(Level.SEVERE, String.format("Coordination service error while reprocessing %s", manifestPath), ex);
@ -755,7 +760,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString())); AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString()));
AutoIngestJob deletedJob = new AutoIngestJob(nodeData); AutoIngestJob deletedJob = new AutoIngestJob(nodeData);
deletedJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.DELETED); deletedJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.DELETED);
this.updateCoordinationServiceNode(deletedJob); this.updateCoordinationServiceManifestNode(deletedJob);
} catch (AutoIngestJobNodeData.InvalidDataException | AutoIngestJobException ex) { } catch (AutoIngestJobNodeData.InvalidDataException | AutoIngestJobException ex) {
SYS_LOGGER.log(Level.WARNING, String.format("Invalid auto ingest job node data for %s", manifestPath), ex); SYS_LOGGER.log(Level.WARNING, String.format("Invalid auto ingest job node data for %s", manifestPath), ex);
return CaseDeletionResult.PARTIALLY_DELETED; return CaseDeletionResult.PARTIALLY_DELETED;
@ -865,21 +870,37 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} }
/** /**
* Sets the coordination service node data for an auto ingest job. * Sets the coordination service manifest node.
* *
* Note that a new auto ingest node data object will be created from the job * Note that a new auto ingest job node data object will be created from the
* passed in. Thus, if the data version of the node has changed, the node * job passed in. Thus, if the data version of the node has changed, the
* will be "upgraded" as well as updated. * node will be "upgraded" as well as updated.
* *
* @param job The auto ingest job. * @param job The auto ingest job.
*/ */
void updateCoordinationServiceNode(AutoIngestJob job) throws CoordinationServiceException, InterruptedException { void updateCoordinationServiceManifestNode(AutoIngestJob job) throws CoordinationServiceException, InterruptedException {
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(job); AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(job);
String manifestNodePath = job.getManifest().getFilePath().toString(); String manifestNodePath = job.getManifest().getFilePath().toString();
byte[] rawData = nodeData.toArray(); byte[] rawData = nodeData.toArray();
coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath, rawData); coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath, rawData);
} }
/**
* Sets the error flag for case node data given a case directory path.
*
* @param caseDirectoryPath The case directory path.
*
* @throws CoordinationService.CoordinationServiceException
* @throws InterruptedException
* @throws CaseNodeData.InvalidDataException
*/
private void setCaseNodeDataErrorsOccurred(Path caseDirectoryPath) throws CoordinationServiceException, InterruptedException, CaseNodeData.InvalidDataException {
CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString()));
caseNodeData.setErrorsOccurred(true);
byte[] rawData = caseNodeData.toArray();
coordinationService.setNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString(), rawData);
}
/** /**
* A task that submits an input directory scan task to the input directory * A task that submits an input directory scan task to the input directory
* scan task executor. * scan task executor.
@ -1041,8 +1062,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
if (null != manifest) { if (null != manifest) {
/* /*
* Update the mapping of case names to manifest paths that is * Update the mapping of case names to manifest paths that
* used for case deletion. * is used for case deletion.
*/ */
String caseName = manifest.getCaseName(); String caseName = manifest.getCaseName();
Path manifestPath = manifest.getFilePath(); Path manifestPath = manifest.getFilePath();
@ -1056,8 +1077,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} }
/* /*
* Add a job to the pending jobs queue, the completed jobs list, * Add a job to the pending jobs queue, the completed jobs
* or do crashed job recovery, as required. * list, or do crashed job recovery, as required.
*/ */
try { try {
byte[] rawData = coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString()); byte[] rawData = coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString());
@ -1077,7 +1098,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
break; break;
case DELETED: case DELETED:
/* /*
* Ignore jobs marked as "deleted." * Ignore jobs marked as "deleted."
*/ */
break; break;
default: default:
@ -1147,8 +1168,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} }
/* /*
* Try to upgrade/update the coordination service node data for * Try to upgrade/update the coordination service manifest node
* the job. * data for the job.
* *
* An exclusive lock is obtained before doing so because another * An exclusive lock is obtained before doing so because another
* host may have already found the job, obtained an exclusive * host may have already found the job, obtained an exclusive
@ -1161,7 +1182,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
*/ */
try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) { try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) {
if (null != manifestLock) { if (null != manifestLock) {
updateCoordinationServiceNode(job); updateCoordinationServiceManifestNode(job);
} }
} catch (CoordinationServiceException ex) { } catch (CoordinationServiceException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifest.getFilePath()), ex); SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifest.getFilePath()), ex);
@ -1186,9 +1207,9 @@ public final class AutoIngestManager extends Observable implements PropertyChang
*/ */
private void addNewPendingJob(Manifest manifest) throws InterruptedException, AutoIngestJobException { private void addNewPendingJob(Manifest manifest) throws InterruptedException, AutoIngestJobException {
/* /*
* Create the coordination service node data for the job. Note that * Create the coordination service manifest node data for the job.
* getting the lock will create the node for the job (with no data) * Note that getting the lock will create the node for the job (with
* if it does not already exist. * no data) if it does not already exist.
* *
* An exclusive lock is obtained before creating the node data * An exclusive lock is obtained before creating the node data
* because another host may have already found the job, obtained an * because another host may have already found the job, obtained an
@ -1202,7 +1223,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) { try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) {
if (null != manifestLock) { if (null != manifestLock) {
AutoIngestJob job = new AutoIngestJob(manifest); AutoIngestJob job = new AutoIngestJob(manifest);
updateCoordinationServiceNode(job); updateCoordinationServiceManifestNode(job);
newPendingJobsList.add(job); newPendingJobsList.add(job);
} }
} catch (CoordinationServiceException ex) { } catch (CoordinationServiceException ex) {
@ -1218,15 +1239,17 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* the node that was processing the job crashed and the processing * the node that was processing the job crashed and the processing
* status was not updated. * status was not updated.
* *
* @param manifest The manifest for upgrading the node. * @param manifest The manifest for upgrading the node.
* @param nodeData The node data. * @param jobNodeData The auto ingest job node data.
* *
* @throws InterruptedException if the thread running the input * @throws InterruptedException if the thread running the input
* directory scan task is interrupted while * directory scan task is interrupted
* blocked, i.e., if auto ingest is * while blocked, i.e., if auto ingest is
* shutting down. * shutting down.
* @throws AutoIngestJobException if there is an issue creating a new
* AutoIngestJob object.
*/ */
private void doRecoveryIfCrashed(Manifest manifest, AutoIngestJobNodeData nodeData) throws InterruptedException, AutoIngestJobException { private void doRecoveryIfCrashed(Manifest manifest, AutoIngestJobNodeData jobNodeData) throws InterruptedException, AutoIngestJobException {
/* /*
* Try to get an exclusive lock on the coordination service node for * Try to get an exclusive lock on the coordination service node for
* the job. If the lock cannot be obtained, another host in the auto * the job. If the lock cannot be obtained, another host in the auto
@ -1237,48 +1260,35 @@ public final class AutoIngestManager extends Observable implements PropertyChang
if (null != manifestLock) { if (null != manifestLock) {
SYS_LOGGER.log(Level.SEVERE, "Attempting crash recovery for {0}", manifestPath); SYS_LOGGER.log(Level.SEVERE, "Attempting crash recovery for {0}", manifestPath);
try { try {
Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, manifest.getCaseName());
/* /*
* Create the recovery job. * Create the recovery job.
*/ */
AutoIngestJob job = new AutoIngestJob(nodeData); AutoIngestJob job = new AutoIngestJob(jobNodeData);
int numberOfCrashes = job.getNumberOfCrashes(); int numberOfCrashes = job.getNumberOfCrashes();
++numberOfCrashes; if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) {
job.setNumberOfCrashes(numberOfCrashes); ++numberOfCrashes;
job.setCompletedDate(new Date(0)); job.setNumberOfCrashes(numberOfCrashes);
Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, manifest.getCaseName()); if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) {
job.setCompletedDate(new Date(0));
} else {
job.setCompletedDate(Date.from(Instant.now()));
}
}
if (null != caseDirectoryPath) { if (null != caseDirectoryPath) {
job.setCaseDirectoryPath(caseDirectoryPath); job.setCaseDirectoryPath(caseDirectoryPath);
job.setErrorsOccurred(true); job.setErrorsOccurred(true);
try {
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
} catch (CaseNodeData.InvalidDataException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to get case node data for %s", caseDirectoryPath), ex);
}
} else { } else {
job.setErrorsOccurred(false); job.setErrorsOccurred(false);
} }
/*
* Update the coordination service node for the job. If
* this fails, leave the recovery to another host.
*/
try {
updateCoordinationServiceNode(job);
if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) {
newPendingJobsList.add(job);
} else {
newCompletedJobsList.add(new AutoIngestJob(nodeData));
}
} catch (CoordinationServiceException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifestPath), ex);
return;
}
/*
* Write the alert file and do the logging.
*/
if (null != caseDirectoryPath) {
try {
AutoIngestAlertFile.create(nodeData.getCaseDirectoryPath());
} catch (AutoIngestAlertFileException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error creating alert file for crashed job for %s", manifestPath), ex);
}
}
if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) { if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) {
job.setProcessingStatus(AutoIngestJob.ProcessingStatus.PENDING); job.setProcessingStatus(AutoIngestJob.ProcessingStatus.PENDING);
if (null != caseDirectoryPath) { if (null != caseDirectoryPath) {
@ -1292,13 +1302,32 @@ public final class AutoIngestManager extends Observable implements PropertyChang
job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED); job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED);
if (null != caseDirectoryPath) { if (null != caseDirectoryPath) {
try { try {
new AutoIngestJobLogger(manifest.getFilePath(), manifest.getDataSourceFileName(), nodeData.getCaseDirectoryPath()).logCrashRecoveryNoRetry(); new AutoIngestJobLogger(manifest.getFilePath(), manifest.getDataSourceFileName(), caseDirectoryPath).logCrashRecoveryNoRetry();
} catch (AutoIngestJobLoggerException ex) { } catch (AutoIngestJobLoggerException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error creating case auto ingest log entry for crashed job for %s", manifestPath), ex); SYS_LOGGER.log(Level.SEVERE, String.format("Error creating case auto ingest log entry for crashed job for %s", manifestPath), ex);
} }
} }
} }
/*
* Update the coordination service node for the job. If
* this fails, leave the recovery to another host.
*/
try {
updateCoordinationServiceManifestNode(job);
} catch (CoordinationServiceException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifestPath), ex);
return;
}
jobNodeData = new AutoIngestJobNodeData(job);
if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) {
newPendingJobsList.add(job);
} else {
newCompletedJobsList.add(new AutoIngestJob(jobNodeData));
}
} finally { } finally {
try { try {
manifestLock.release(); manifestLock.release();
@ -1352,15 +1381,15 @@ public final class AutoIngestManager extends Observable implements PropertyChang
job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED); job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED);
/* /*
* Try to upgrade/update the coordination service node data * Try to upgrade/update the coordination service manifest
* for the job. It is possible that two hosts will both try * node data for the job. It is possible that two hosts will
* to obtain the lock to do the upgrade operation at the * both try to obtain the lock to do the upgrade operation
* same time. If this happens, the host that is holding the * at the same time. If this happens, the host that is
* lock will complete the upgrade operation. * holding the lock will complete the upgrade operation.
*/ */
try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) { try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) {
if (null != manifestLock) { if (null != manifestLock) {
updateCoordinationServiceNode(job); updateCoordinationServiceManifestNode(job);
} }
} catch (CoordinationServiceException ex) { } catch (CoordinationServiceException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifest.getFilePath()), ex); SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifest.getFilePath()), ex);
@ -1507,8 +1536,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
errorState = ErrorState.ANALYSIS_STARTUP_ERROR; errorState = ErrorState.ANALYSIS_STARTUP_ERROR;
} else if (ex instanceof FileExportException) { } else if (ex instanceof FileExportException) {
errorState = ErrorState.FILE_EXPORT_ERROR; errorState = ErrorState.FILE_EXPORT_ERROR;
} else if (ex instanceof AutoIngestAlertFileException) {
errorState = ErrorState.ALERT_FILE_ERROR;
} else if (ex instanceof AutoIngestJobLoggerException) { } else if (ex instanceof AutoIngestJobLoggerException) {
errorState = ErrorState.JOB_LOGGER_ERROR; errorState = ErrorState.JOB_LOGGER_ERROR;
} else if (ex instanceof AutoIngestDataSourceProcessorException) { } else if (ex instanceof AutoIngestDataSourceProcessorException) {
@ -1691,9 +1718,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* @throws FileExportException if there is an * @throws FileExportException if there is an
* error exporting * error exporting
* files. * files.
* @throws AutoIngestAlertFileException if there is an
* error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an * @throws AutoIngestJobLoggerException if there is an
* error writing to * error writing to
* the auto ingest * the auto ingest
@ -1710,7 +1734,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* auto ingest node * auto ingest node
* data objects. * data objects.
*/ */
private void processJobs() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, AutoIngestJobNodeData.InvalidDataException { private void processJobs() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, AutoIngestJobNodeData.InvalidDataException, CaseNodeData.InvalidDataException {
SYS_LOGGER.log(Level.INFO, "Started processing pending jobs queue"); SYS_LOGGER.log(Level.INFO, "Started processing pending jobs queue");
Lock manifestLock = JobProcessingTask.this.dequeueAndLockNextJob(); Lock manifestLock = JobProcessingTask.this.dequeueAndLockNextJob();
while (null != manifestLock) { while (null != manifestLock) {
@ -1890,9 +1914,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* @throws FileExportException if there is an * @throws FileExportException if there is an
* error exporting * error exporting
* files. * files.
* @throws AutoIngestAlertFileException if there is an
* error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an * @throws AutoIngestJobLoggerException if there is an
* error writing to * error writing to
* the auto ingest * the auto ingest
@ -1909,13 +1930,13 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* auto ingest node * auto ingest node
* data objects. * data objects.
*/ */
private void processJob() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, AutoIngestJobNodeData.InvalidDataException { private void processJob() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, CaseNodeData.InvalidDataException {
Path manifestPath = currentJob.getManifest().getFilePath(); Path manifestPath = currentJob.getManifest().getFilePath();
SYS_LOGGER.log(Level.INFO, "Started processing of {0}", manifestPath); SYS_LOGGER.log(Level.INFO, "Started processing of {0}", manifestPath);
currentJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.PROCESSING); currentJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.PROCESSING);
currentJob.setProcessingStage(AutoIngestJob.Stage.STARTING, Date.from(Instant.now())); currentJob.setProcessingStage(AutoIngestJob.Stage.STARTING, Date.from(Instant.now()));
currentJob.setProcessingHostName(AutoIngestManager.LOCAL_HOST_NAME); currentJob.setProcessingHostName(AutoIngestManager.LOCAL_HOST_NAME);
updateCoordinationServiceNode(currentJob); updateCoordinationServiceManifestNode(currentJob);
setChanged(); setChanged();
notifyObservers(Event.JOB_STARTED); notifyObservers(Event.JOB_STARTED);
eventPublisher.publishRemotely(new AutoIngestJobStartedEvent(currentJob)); eventPublisher.publishRemotely(new AutoIngestJobStartedEvent(currentJob));
@ -1939,14 +1960,14 @@ public final class AutoIngestManager extends Observable implements PropertyChang
currentJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.PENDING); currentJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.PENDING);
} }
currentJob.setProcessingHostName(""); currentJob.setProcessingHostName("");
updateCoordinationServiceNode(currentJob); updateCoordinationServiceManifestNode(currentJob);
boolean retry = (!currentJob.isCanceled() && !currentJob.isCompleted()); boolean retry = (!currentJob.isCanceled() && !currentJob.isCompleted());
SYS_LOGGER.log(Level.INFO, "Completed processing of {0}, retry = {1}", new Object[]{manifestPath, retry}); SYS_LOGGER.log(Level.INFO, "Completed processing of {0}, retry = {1}", new Object[]{manifestPath, retry});
if (currentJob.isCanceled()) { if (currentJob.isCanceled()) {
Path caseDirectoryPath = currentJob.getCaseDirectoryPath(); Path caseDirectoryPath = currentJob.getCaseDirectoryPath();
if (null != caseDirectoryPath) { if (null != caseDirectoryPath) {
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, currentJob.getManifest().getDataSourceFileName(), caseDirectoryPath); AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, currentJob.getManifest().getDataSourceFileName(), caseDirectoryPath);
jobLogger.logJobCancelled(); jobLogger.logJobCancelled();
} }
@ -1994,7 +2015,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* i.e., if auto ingest is * i.e., if auto ingest is
* shutting down. * shutting down.
*/ */
private void attemptJob() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException { private void attemptJob() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, CaseNodeData.InvalidDataException {
updateConfiguration(); updateConfiguration();
if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) { if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) {
return; return;
@ -2115,7 +2136,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
Case.openAsCurrentCase(metadataFilePath.toString()); Case.openAsCurrentCase(metadataFilePath.toString());
} else { } else {
caseDirectoryPath = PathUtils.createCaseFolderPath(rootOutputDirectory, caseName); caseDirectoryPath = PathUtils.createCaseFolderPath(rootOutputDirectory, caseName);
Case.createAsCurrentCase(caseDirectoryPath.toString(), caseName, "", "", CaseType.MULTI_USER_CASE); CaseDetails caseDetails = new CaseDetails(caseName);
Case.createAsCurrentCase(CaseType.MULTI_USER_CASE, caseDirectoryPath.toString(), caseDetails);
/* /*
* Sleep a bit before releasing the lock to ensure * Sleep a bit before releasing the lock to ensure
* that the new case folder is visible on the * that the new case folder is visible on the
@ -2158,8 +2180,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* level ingest modules. * level ingest modules.
* @throws FileExportException if there is an error exporting * @throws FileExportException if there is an error exporting
* files. * files.
* @throws AutoIngestAlertFileException if there is an error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to * @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the * the auto ingest log for the
* case. * case.
@ -2168,7 +2188,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto * while blocked, i.e., if auto
* ingest is shutting down. * ingest is shutting down.
*/ */
private void runIngestForJob(Case caseForJob) throws CoordinationServiceException, AnalysisStartupException, FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException { private void runIngestForJob(Case caseForJob) throws CoordinationServiceException, AnalysisStartupException, FileExportException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, CaseNodeData.InvalidDataException {
try { try {
if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) { if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) {
return; return;
@ -2196,8 +2216,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* level ingest modules. * level ingest modules.
* @throws FileExportException if there is an error exporting * @throws FileExportException if there is an error exporting
* files. * files.
* @throws AutoIngestAlertFileException if there is an error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to * @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the * the auto ingest log for the
* case. * case.
@ -2206,7 +2224,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto * while blocked, i.e., if auto
* ingest is shutting down. * ingest is shutting down.
*/ */
private void ingestDataSource(Case caseForJob) throws AnalysisStartupException, FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException { private void ingestDataSource(Case caseForJob) throws AnalysisStartupException, FileExportException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, CaseNodeData.InvalidDataException, CoordinationServiceException {
if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) { if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) {
return; return;
} }
@ -2254,8 +2272,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* *
* @return A data source object. * @return A data source object.
* *
* @throws AutoIngestAlertFileException if there is an error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to * @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the * the auto ingest log for the
* case. * case.
@ -2264,7 +2280,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* interrupted while blocked, i.e., * interrupted while blocked, i.e.,
* if auto ingest is shutting down. * if auto ingest is shutting down.
*/ */
private DataSource identifyDataSource() throws AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException { private DataSource identifyDataSource() throws AutoIngestJobLoggerException, InterruptedException, CaseNodeData.InvalidDataException, CoordinationServiceException {
Manifest manifest = currentJob.getManifest(); Manifest manifest = currentJob.getManifest();
Path manifestPath = manifest.getFilePath(); Path manifestPath = manifest.getFilePath();
SYS_LOGGER.log(Level.INFO, "Identifying data source for {0} ", manifestPath); SYS_LOGGER.log(Level.INFO, "Identifying data source for {0} ", manifestPath);
@ -2276,7 +2292,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
if (!dataSource.exists()) { if (!dataSource.exists()) {
SYS_LOGGER.log(Level.SEVERE, "Missing data source for {0}", manifestPath); SYS_LOGGER.log(Level.SEVERE, "Missing data source for {0}", manifestPath);
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logMissingDataSource(); jobLogger.logMissingDataSource();
return null; return null;
} }
@ -2290,8 +2306,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* *
* @param dataSource The data source. * @param dataSource The data source.
* *
* @throws AutoIngestAlertFileException if there is an error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to * @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the * the auto ingest log for the
* case. * case.
@ -2300,7 +2314,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto * while blocked, i.e., if auto
* ingest is shutting down. * ingest is shutting down.
*/ */
private void runDataSourceProcessor(Case caseForJob, DataSource dataSource) throws InterruptedException, AutoIngestAlertFileException, AutoIngestJobLoggerException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException { private void runDataSourceProcessor(Case caseForJob, DataSource dataSource) throws InterruptedException, AutoIngestJobLoggerException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, CaseNodeData.InvalidDataException, CoordinationServiceException {
Manifest manifest = currentJob.getManifest(); Manifest manifest = currentJob.getManifest();
Path manifestPath = manifest.getFilePath(); Path manifestPath = manifest.getFilePath();
SYS_LOGGER.log(Level.INFO, "Adding data source for {0} ", manifestPath); SYS_LOGGER.log(Level.INFO, "Adding data source for {0} ", manifestPath);
@ -2326,7 +2340,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
// did we find a data source processor that can process the data source // did we find a data source processor that can process the data source
if (validDataSourceProcessorsMap.isEmpty()) { if (validDataSourceProcessorsMap.isEmpty()) {
// This should never happen. We should add all unsupported data sources as logical files. // This should never happen. We should add all unsupported data sources as logical files.
AutoIngestAlertFile.create(caseDirectoryPath); setCaseNodeDataErrorsOccurred(caseDirectoryPath);
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
jobLogger.logFailedToIdentifyDataSource(); jobLogger.logFailedToIdentifyDataSource();
SYS_LOGGER.log(Level.WARNING, "Unsupported data source {0} for {1}", new Object[]{dataSource.getPath(), manifestPath}); // NON-NLS SYS_LOGGER.log(Level.WARNING, "Unsupported data source {0} for {1}", new Object[]{dataSource.getPath(), manifestPath}); // NON-NLS
@ -2352,7 +2366,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
// Log that the current DSP failed and set the error flag. We consider it an error // Log that the current DSP failed and set the error flag. We consider it an error
// if a DSP fails even if a later one succeeds since we expected to be able to process // if a DSP fails even if a later one succeeds since we expected to be able to process
// the data source which each DSP on the list. // the data source which each DSP on the list.
AutoIngestAlertFile.create(caseDirectoryPath); setCaseNodeDataErrorsOccurred(caseDirectoryPath);
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
jobLogger.logDataSourceProcessorError(selectedProcessor.getDataSourceType()); jobLogger.logDataSourceProcessorError(selectedProcessor.getDataSourceType());
SYS_LOGGER.log(Level.SEVERE, "Exception while processing {0} with data source processor {1}", new Object[]{dataSource.getPath(), selectedProcessor.getDataSourceType()}); SYS_LOGGER.log(Level.SEVERE, "Exception while processing {0} with data source processor {1}", new Object[]{dataSource.getPath(), selectedProcessor.getDataSourceType()});
@ -2376,8 +2390,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* *
* @param dataSource The data source. * @param dataSource The data source.
* *
* @throws AutoIngestAlertFileException if there is an error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to * @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the * the auto ingest log for the
* case. * case.
@ -2386,7 +2398,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto * while blocked, i.e., if auto
* ingest is shutting down. * ingest is shutting down.
*/ */
private void logDataSourceProcessorResult(DataSource dataSource) throws AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException { private void logDataSourceProcessorResult(DataSource dataSource) throws AutoIngestJobLoggerException, InterruptedException, CaseNodeData.InvalidDataException, CoordinationServiceException {
Manifest manifest = currentJob.getManifest(); Manifest manifest = currentJob.getManifest();
Path manifestPath = manifest.getFilePath(); Path manifestPath = manifest.getFilePath();
Path caseDirectoryPath = currentJob.getCaseDirectoryPath(); Path caseDirectoryPath = currentJob.getCaseDirectoryPath();
@ -2398,7 +2410,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
jobLogger.logDataSourceAdded(); jobLogger.logDataSourceAdded();
if (dataSource.getContent().isEmpty()) { if (dataSource.getContent().isEmpty()) {
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logNoDataSourceContent(); jobLogger.logNoDataSourceContent();
} }
break; break;
@ -2410,7 +2422,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
jobLogger.logDataSourceAdded(); jobLogger.logDataSourceAdded();
if (dataSource.getContent().isEmpty()) { if (dataSource.getContent().isEmpty()) {
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logNoDataSourceContent(); jobLogger.logNoDataSourceContent();
} }
break; break;
@ -2420,7 +2432,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
SYS_LOGGER.log(Level.SEVERE, "Critical error running data source processor for {0}: {1}", new Object[]{manifestPath, errorMessage}); SYS_LOGGER.log(Level.SEVERE, "Critical error running data source processor for {0}: {1}", new Object[]{manifestPath, errorMessage});
} }
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logFailedToAddDataSource(); jobLogger.logFailedToAddDataSource();
break; break;
} }
@ -2434,7 +2446,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
*/ */
SYS_LOGGER.log(Level.WARNING, "Cancellation while waiting for data source processor for {0}", manifestPath); SYS_LOGGER.log(Level.WARNING, "Cancellation while waiting for data source processor for {0}", manifestPath);
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logDataSourceProcessorCancelled(); jobLogger.logDataSourceProcessorCancelled();
} }
} }
@ -2448,8 +2460,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* *
* @throws AnalysisStartupException if there is an error analyzing * @throws AnalysisStartupException if there is an error analyzing
* the data source. * the data source.
* @throws AutoIngestAlertFileException if there is an error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to * @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the * the auto ingest log for the
* case. * case.
@ -2458,7 +2468,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto * while blocked, i.e., if auto
* ingest is shutting down. * ingest is shutting down.
*/ */
private void analyze(DataSource dataSource) throws AnalysisStartupException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException { private void analyze(DataSource dataSource) throws AnalysisStartupException, AutoIngestJobLoggerException, InterruptedException, CaseNodeData.InvalidDataException, CoordinationServiceException {
Manifest manifest = currentJob.getManifest(); Manifest manifest = currentJob.getManifest();
Path manifestPath = manifest.getFilePath(); Path manifestPath = manifest.getFilePath();
SYS_LOGGER.log(Level.INFO, "Starting ingest modules analysis for {0} ", manifestPath); SYS_LOGGER.log(Level.INFO, "Starting ingest modules analysis for {0} ", manifestPath);
@ -2490,7 +2500,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
if (!cancelledModules.isEmpty()) { if (!cancelledModules.isEmpty()) {
SYS_LOGGER.log(Level.WARNING, String.format("Ingest module(s) cancelled for %s", manifestPath)); SYS_LOGGER.log(Level.WARNING, String.format("Ingest module(s) cancelled for %s", manifestPath));
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
for (String module : snapshot.getCancelledDataSourceIngestModules()) { for (String module : snapshot.getCancelledDataSourceIngestModules()) {
SYS_LOGGER.log(Level.WARNING, String.format("%s ingest module cancelled for %s", module, manifestPath)); SYS_LOGGER.log(Level.WARNING, String.format("%s ingest module cancelled for %s", module, manifestPath));
jobLogger.logIngestModuleCancelled(module); jobLogger.logIngestModuleCancelled(module);
@ -2500,7 +2510,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} else { } else {
currentJob.setProcessingStage(AutoIngestJob.Stage.CANCELLING, Date.from(Instant.now())); currentJob.setProcessingStage(AutoIngestJob.Stage.CANCELLING, Date.from(Instant.now()));
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logAnalysisCancelled(); jobLogger.logAnalysisCancelled();
CancellationReason cancellationReason = snapshot.getCancellationReason(); CancellationReason cancellationReason = snapshot.getCancellationReason();
if (CancellationReason.NOT_CANCELLED != cancellationReason && CancellationReason.USER_CANCELLED != cancellationReason) { if (CancellationReason.NOT_CANCELLED != cancellationReason && CancellationReason.USER_CANCELLED != cancellationReason) {
@ -2513,13 +2523,13 @@ public final class AutoIngestManager extends Observable implements PropertyChang
SYS_LOGGER.log(Level.SEVERE, String.format("%s ingest module startup error for %s", error.getModuleDisplayName(), manifestPath), error.getThrowable()); SYS_LOGGER.log(Level.SEVERE, String.format("%s ingest module startup error for %s", error.getModuleDisplayName(), manifestPath), error.getThrowable());
} }
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logIngestModuleStartupErrors(); jobLogger.logIngestModuleStartupErrors();
throw new AnalysisStartupException(String.format("Error(s) during ingest module startup for %s", manifestPath)); throw new AnalysisStartupException(String.format("Error(s) during ingest module startup for %s", manifestPath));
} else { } else {
SYS_LOGGER.log(Level.SEVERE, String.format("Ingest manager ingest job start error for %s", manifestPath), ingestJobStartResult.getStartupException()); SYS_LOGGER.log(Level.SEVERE, String.format("Ingest manager ingest job start error for %s", manifestPath), ingestJobStartResult.getStartupException());
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logAnalysisStartupError(); jobLogger.logAnalysisStartupError();
throw new AnalysisStartupException("Ingest manager error starting job", ingestJobStartResult.getStartupException()); throw new AnalysisStartupException("Ingest manager error starting job", ingestJobStartResult.getStartupException());
} }
@ -2528,7 +2538,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
SYS_LOGGER.log(Level.SEVERE, "Ingest job settings error for {0}: {1}", new Object[]{manifestPath, warning}); SYS_LOGGER.log(Level.SEVERE, "Ingest job settings error for {0}: {1}", new Object[]{manifestPath, warning});
} }
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logIngestJobSettingsErrors(); jobLogger.logIngestJobSettingsErrors();
throw new AnalysisStartupException("Error(s) in ingest job settings"); throw new AnalysisStartupException("Error(s) in ingest job settings");
} }
@ -2547,8 +2557,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* *
* @throws FileExportException if there is an error exporting * @throws FileExportException if there is an error exporting
* the files. * the files.
* @throws AutoIngestAlertFileException if there is an error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to * @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the * the auto ingest log for the
* case. * case.
@ -2557,7 +2565,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto * while blocked, i.e., if auto
* ingest is shutting down. * ingest is shutting down.
*/ */
private void exportFiles(DataSource dataSource) throws FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException { private void exportFiles(DataSource dataSource) throws FileExportException, AutoIngestJobLoggerException, InterruptedException, CaseNodeData.InvalidDataException, CoordinationServiceException {
Manifest manifest = currentJob.getManifest(); Manifest manifest = currentJob.getManifest();
Path manifestPath = manifest.getFilePath(); Path manifestPath = manifest.getFilePath();
SYS_LOGGER.log(Level.INFO, "Exporting files for {0}", manifestPath); SYS_LOGGER.log(Level.INFO, "Exporting files for {0}", manifestPath);
@ -2573,7 +2581,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} catch (FileExportException ex) { } catch (FileExportException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error doing file export for %s", manifestPath), ex); SYS_LOGGER.log(Level.SEVERE, String.format("Error doing file export for %s", manifestPath), ex);
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logFileExportError(); jobLogger.logFileExportError();
} }
} }
@ -2739,7 +2747,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
currentJob.getProcessingStageDetails(); currentJob.getProcessingStageDetails();
setChanged(); setChanged();
notifyObservers(Event.JOB_STATUS_UPDATED); notifyObservers(Event.JOB_STATUS_UPDATED);
updateCoordinationServiceNode(currentJob); updateCoordinationServiceManifestNode(currentJob);
eventPublisher.publishRemotely(new AutoIngestJobStatusEvent(currentJob)); eventPublisher.publishRemotely(new AutoIngestJobStatusEvent(currentJob));
} }
@ -2842,7 +2850,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
CASE_MANAGEMENT_ERROR("Case management error"), CASE_MANAGEMENT_ERROR("Case management error"),
ANALYSIS_STARTUP_ERROR("Analysis startup error"), ANALYSIS_STARTUP_ERROR("Analysis startup error"),
FILE_EXPORT_ERROR("File export error"), FILE_EXPORT_ERROR("File export error"),
ALERT_FILE_ERROR("Alert file error"),
JOB_LOGGER_ERROR("Job logger error"), JOB_LOGGER_ERROR("Job logger error"),
DATA_SOURCE_PROCESSOR_ERROR("Data source processor error"), DATA_SOURCE_PROCESSOR_ERROR("Data source processor error"),
UNEXPECTED_EXCEPTION("Unknown error"); UNEXPECTED_EXCEPTION("Unknown error");

View File

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="2"/>
<Property name="alwaysOnTop" type="boolean" value="true"/>
<Property name="resizable" type="boolean" value="false"/>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<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"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="metricsButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="datePicker" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="33" max="32767" attributes="0"/>
<Component id="closeButton" min="-2" pref="70" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" min="-2" pref="128" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" groupAlignment="3" attributes="0">
<Component id="closeButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="metricsButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="datePicker" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JButton" name="closeButton">
<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="AutoIngestMetricsDialog.closeButton.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="closeButtonActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextArea" name="reportTextArea">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="columns" type="int" value="20"/>
<Property name="rows" type="int" value="5"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestMetricsDialog.reportTextArea.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="metricsButton">
<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="AutoIngestMetricsDialog.metricsButton.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="metricsButtonActionPerformed"/>
</Events>
</Component>
<Component class="com.github.lgooddatepicker.datepicker.DatePicker" name="datePicker">
<Properties>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestMetricsDialog.datePicker.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new DatePicker();"/>
</AuxValues>
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,178 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 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 com.github.lgooddatepicker.datepicker.DatePicker;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Window;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.time.ZoneOffset;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
/**
* Display basic metrics for a cluster.
*/
final class AutoIngestMetricsDialog extends javax.swing.JDialog {
private final AutoIngestMonitor autoIngestMonitor;
/**
* Creates new form AutoIngestMetricsDialog
*
* @param parent The parent container.
* @param autoIngestMonitor The auto ingest monitor.
*/
@Messages({
"AutoIngestMetricsDialog.title.text=Auto Ingest Cluster Metrics",
"AutoIngestMetricsDialog.initReportText=Select a date below and click the 'Get Metrics Since...' button to generate\na metrics report."
})
AutoIngestMetricsDialog(Container parent, AutoIngestMonitor autoIngestMonitor) {
super((Window) parent, NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.title.text"), ModalityType.MODELESS);
initComponents();
reportTextArea.setText(NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.initReportText"));
this.autoIngestMonitor = autoIngestMonitor;
setModal(true);
setSize(getPreferredSize());
setLocationRelativeTo(parent);
setVisible(true);
}
/**
* Update the metrics shown in the report text area.
*/
private void updateMetrics() {
if(datePicker.getDate() == null) {
return;
}
AutoIngestMonitor.MetricsSnapshot metricsSnapshot = autoIngestMonitor.getMetricsSnapshot();
Object[] completedJobDates = metricsSnapshot.getCompletedJobDates().toArray();
int count = 0;
long pickedDate = datePicker.getDate().atStartOfDay().toEpochSecond(ZoneOffset.UTC) * 1000;
for(int i = completedJobDates.length - 1; i >= 0; i--) {
if((Long)completedJobDates[i] >= pickedDate) {
count++;
}
}
SimpleDateFormat dateFormatter = new SimpleDateFormat("MMM d, yyyy");
reportTextArea.setText(String.format(
"Since %s:\n" +
"\tNumber of Jobs Completed: %d\n",
dateFormatter.format(Date.valueOf(datePicker.getDate())),
count
));
}
/**
* 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() {
closeButton = new javax.swing.JButton();
jScrollPane1 = new javax.swing.JScrollPane();
reportTextArea = new javax.swing.JTextArea();
metricsButton = new javax.swing.JButton();
datePicker = new DatePicker();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setAlwaysOnTop(true);
setResizable(false);
org.openide.awt.Mnemonics.setLocalizedText(closeButton, org.openide.util.NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.closeButton.text")); // NOI18N
closeButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
closeButtonActionPerformed(evt);
}
});
reportTextArea.setEditable(false);
reportTextArea.setColumns(20);
reportTextArea.setRows(5);
reportTextArea.setText(org.openide.util.NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.reportTextArea.text")); // NOI18N
jScrollPane1.setViewportView(reportTextArea);
org.openide.awt.Mnemonics.setLocalizedText(metricsButton, org.openide.util.NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.metricsButton.text")); // NOI18N
metricsButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
metricsButtonActionPerformed(evt);
}
});
datePicker.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.datePicker.toolTipText")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1)
.addGroup(layout.createSequentialGroup()
.addComponent(metricsButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(datePicker, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 33, Short.MAX_VALUE)
.addComponent(closeButton, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 128, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(closeButton)
.addComponent(metricsButton))
.addComponent(datePicker, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
setVisible(false);
dispose();
}//GEN-LAST:event_closeButtonActionPerformed
private void metricsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_metricsButtonActionPerformed
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
updateMetrics();
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}//GEN-LAST:event_metricsButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton closeButton;
private com.github.lgooddatepicker.datepicker.DatePicker datePicker;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JButton metricsButton;
private javax.swing.JTextArea reportTextArea;
// End of variables declaration//GEN-END:variables
}

View File

@ -23,10 +23,12 @@ import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Observable; import java.util.Observable;
import java.util.Set; import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Level; import java.util.logging.Level;
@ -43,7 +45,7 @@ import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJob.ProcessingSta
* An auto ingest monitor responsible for monitoring and reporting the * An auto ingest monitor responsible for monitoring and reporting the
* processing of auto ingest jobs. * processing of auto ingest jobs.
*/ */
public final class AutoIngestMonitor extends Observable implements PropertyChangeListener { final class AutoIngestMonitor extends Observable implements PropertyChangeListener {
private static final Logger LOGGER = Logger.getLogger(AutoIngestMonitor.class.getName()); private static final Logger LOGGER = Logger.getLogger(AutoIngestMonitor.class.getName());
private static final int NUM_COORD_SVC_QUERY_THREADS = 1; private static final int NUM_COORD_SVC_QUERY_THREADS = 1;
@ -265,17 +267,86 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang
} }
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
LOGGER.log(Level.SEVERE, String.format("Unexpected interrupt while retrieving coordination service node data for '%s'", node), ex); LOGGER.log(Level.SEVERE, String.format("Unexpected interrupt while retrieving coordination service node data for '%s'", node), ex);
} catch (AutoIngestJobNodeData.InvalidDataException | AutoIngestJob.AutoIngestJobException ex) { } catch (AutoIngestJobNodeData.InvalidDataException ex) {
LOGGER.log(Level.SEVERE, String.format("Unable to use node data for '%s'", node), ex); LOGGER.log(Level.SEVERE, String.format("Unable to use node data for '%s'", node), ex);
} catch (AutoIngestJob.AutoIngestJobException ex) {
LOGGER.log(Level.SEVERE, String.format("Failed to create a job for '%s'", node), ex);
} }
} }
return newJobsSnapshot; return newJobsSnapshot;
} catch (CoordinationServiceException ex) { } catch (CoordinationServiceException ex) {
LOGGER.log(Level.SEVERE, "Failed to get node list from coordination service", ex); LOGGER.log(Level.SEVERE, "Failed to get node list from coordination service", ex);
return new JobsSnapshot(); return new JobsSnapshot();
} }
} }
/**
* Gets a new metrics snapshot from the coordination service for an auto
* ingest cluster.
*
* @return The metrics snapshot.
*/
private MetricsSnapshot queryCoordinationServiceForMetrics() {
try {
MetricsSnapshot newMetricsSnapshot = new MetricsSnapshot();
List<String> nodeList = coordinationService.getNodeList(CoordinationService.CategoryNode.MANIFESTS);
for (String node : nodeList) {
try {
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, node));
if (nodeData.getVersion() < 1) {
/*
* Ignore version '0' nodes that have not been
* "upgraded" since they don't carry enough data.
*/
continue;
}
AutoIngestJob job = new AutoIngestJob(nodeData);
ProcessingStatus processingStatus = nodeData.getProcessingStatus();
switch (processingStatus) {
case PENDING:
case PROCESSING:
case DELETED:
/*
* These are not jobs we care about for metrics, so
* we will ignore them.
*/
break;
case COMPLETED:
newMetricsSnapshot.addCompletedJobDate(job.getCompletedDate());
break;
default:
LOGGER.log(Level.SEVERE, "Unknown AutoIngestJobData.ProcessingStatus");
break;
}
} catch (InterruptedException ex) {
LOGGER.log(Level.SEVERE, String.format("Unexpected interrupt while retrieving coordination service node data for '%s'", node), ex);
} catch (AutoIngestJobNodeData.InvalidDataException ex) {
LOGGER.log(Level.SEVERE, String.format("Unable to use node data for '%s'", node), ex);
} catch (AutoIngestJob.AutoIngestJobException ex) {
LOGGER.log(Level.SEVERE, String.format("Failed to create a job for '%s'", node), ex);
}
}
return newMetricsSnapshot;
} catch (CoordinationServiceException ex) {
LOGGER.log(Level.SEVERE, "Failed to get node list from coordination service", ex);
return new MetricsSnapshot();
}
}
/**
* Gets a new metrics snapshot. The jobs snapshot will also be updated in
* effect.
*
* @return The metrics snapshot.
*/
public MetricsSnapshot getMetricsSnapshot() {
return queryCoordinationServiceForMetrics();
}
/** /**
* Bumps the priority of all pending ingest jobs for a specified case. * Bumps the priority of all pending ingest jobs for a specified case.
* *
@ -522,6 +593,32 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang
} }
/**
* A snapshot of metrics for an auto ingest cluster.
*/
public static final class MetricsSnapshot {
private final List<Long> completedJobDates = new ArrayList<>();
/**
* Gets a list of completed job dates, formatted in milliseconds.
*
* @return The completed job dates, formatted in milliseconds.
*/
List<Long> getCompletedJobDates() {
return new ArrayList<>(completedJobDates);
}
/**
* Adds a new date to the list of completed job dates.
*
* @param date The date to be added.
*/
void addCompletedJobDate(Date date) {
completedJobDates.add(date.getTime());
}
}
/** /**
* Exception type thrown when there is an error completing an auto ingest * Exception type thrown when there is an error completing an auto ingest
* monitor operation. * monitor operation.

View File

@ -0,0 +1,57 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 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.util.ArrayList;
import java.util.Date;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;
/**
* RowSorter which makes columns whose type is Date to be sorted first in
* Descending order then in Ascending order
*/
class AutoIngestRowSorter<M extends DefaultTableModel> extends TableRowSorter<M> {
AutoIngestRowSorter(M tModel) {
super(tModel);
}
@Override
public void toggleSortOrder(int column) {
if (!this.getModel().getColumnClass(column).equals(Date.class) && !this.getModel().getColumnClass(column).equals(Integer.class)) {
//currently the only Integer column this sorter is being applied to is the Priority column
super.toggleSortOrder(column); //if it isn't a date or Integer column perform the regular sorting
} else {
ArrayList<RowSorter.SortKey> sortKeys = new ArrayList<>(getSortKeys());
if (sortKeys.isEmpty() || sortKeys.get(0).getColumn() != column) { //sort descending
sortKeys.add(0, new RowSorter.SortKey(column, SortOrder.DESCENDING));
} else if (sortKeys.get(0).getSortOrder() == SortOrder.ASCENDING) {
sortKeys.removeIf(key -> key.getColumn() == column);
sortKeys.add(0, new RowSorter.SortKey(column, SortOrder.DESCENDING));
} else {
sortKeys.removeIf(key -> key.getColumn() == column);
sortKeys.add(0, new RowSorter.SortKey(column, SortOrder.ASCENDING));
}
setSortKeys(sortKeys);
}
}
}

View File

@ -1,4 +1,3 @@
CTL_OpenAction=Open Case...
AutoIngestDashboard.lbCompleted.text=Completed Jobs AutoIngestDashboard.lbCompleted.text=Completed Jobs
AutoIngestDashboard.lbRunning.text=Running Jobs AutoIngestDashboard.lbRunning.text=Running Jobs
AutoIngestDashboard.lbPending.text=Pending Jobs AutoIngestDashboard.lbPending.text=Pending Jobs
@ -47,14 +46,10 @@ OpenIDE-Module-Long-Description=\
We make no guarantee that the API of this module will not change, so developers should be careful when relying on it. We make no guarantee that the API of this module will not change, so developers should be careful when relying on it.
OpenIDE-Module-Name=Experimental OpenIDE-Module-Name=Experimental
OpenIDE-Module-Short-Description=This module contains features that are being developed by Basis Technology and are not part of the default Autopsy distribution. OpenIDE-Module-Short-Description=This module contains features that are being developed by Basis Technology and are not part of the default Autopsy distribution.
ReviewModeCasePanel.cannotOpenCase=Cannot Open Case
ReviewModeCasePanel.casePathNotFound=Case path not found
ReviewModeCasePanel.caseIsLocked=Single-user case is locked.
DisplayLogDialog.cannotOpenLog=Unable to open the selected case log file DisplayLogDialog.cannotOpenLog=Unable to open the selected case log file
DisplayLogDialog.cannotFindLog=Unable to find the selected case log file DisplayLogDialog.cannotFindLog=Unable to find the selected case log file
DisplayLogDialog.unableToShowLogFile=Unable to show log file DisplayLogDialog.unableToShowLogFile=Unable to show log file
DisplayLogDialog.okay=Okay DisplayLogDialog.okay=Okay
ReviewModeCasePanel.bnShowLog.text=&Show Log
CopyFilesPanel.lbFrom.text=From Source CopyFilesPanel.lbFrom.text=From Source
CopyFilesPanel.lbTo.text=Destination Case CopyFilesPanel.lbTo.text=Destination Case
CopyFilesPanel.bnCopy.text=&Copy CopyFilesPanel.bnCopy.text=&Copy
@ -128,8 +123,6 @@ CopyFilesPanel.cbThrottleNetwork.toolTipText=<html>Select this box if a low-band
CopyFilesPanel.bnShowCurrentLog.text=Show &Log CopyFilesPanel.bnShowCurrentLog.text=Show &Log
CopyFilesPanel.bnShowCurrentLog.text=Show &Log CopyFilesPanel.bnShowCurrentLog.text=Show &Log
CopyFilesPanel.lbCaseName.text=Case Name CopyFilesPanel.lbCaseName.text=Case Name
CaseStatusIconCellRenderer.tooltiptext.ok=Images processed successfully
CaseStatusIconCellRenderer.tooltiptext.warning=An error occurred or processing was canceled for at least one image - please check the log
OptionsCategory_Name_Case_Import=Case Import OptionsCategory_Name_Case_Import=Case Import
OptionsCategory_Keywords_Case_Import=Case Import Settings OptionsCategory_Keywords_Case_Import=Case Import Settings
CaseImportPanel.validationErrMsg.MUdisabled=Multi user settings must be enabled and saved CaseImportPanel.validationErrMsg.MUdisabled=Multi user settings must be enabled and saved
@ -165,11 +158,6 @@ SingleUserCaseImporter.FailedToComplete=Failed to complete processing of
SingleUserCaseImporter.CompletedBatch=Completed batch processing of SingleUserCaseImporter.CompletedBatch=Completed batch processing of
SingleUserCaseImporter.AbortingBatch=Aborting batch processing of SingleUserCaseImporter.AbortingBatch=Aborting batch processing of
SingleUserCaseImporter.SourceImageMissing=. Source image missing for SingleUserCaseImporter.SourceImageMissing=. Source image missing for
ReviewModeCasePanel.CaseHeaderText=Case
ReviewModeCasePanel.CreatedTimeHeaderText=Created Time
ReviewModeCasePanel.StatusIconHeaderText=Status
ReviewModeCasePanel.OutputFolderHeaderText=Output Folder
ReviewModeCasePanel.LastAccessedTimeHeaderText=Last Accessed Time
CopyFilesPanel.bnOptions.text=&Options CopyFilesPanel.bnOptions.text=&Options
AutoIngestDashboard.lbServicesStatus.text=Services Status: AutoIngestDashboard.lbServicesStatus.text=Services Status:
AutoIngestDashboard.tbServicesStatusMessage.text=Connecting... AutoIngestDashboard.tbServicesStatusMessage.text=Connecting...
@ -231,15 +219,6 @@ FileExporterSettingsPanel.BrowseReportTooltip_1=Browse for the Reports Folder
FileExporterSettingsPanel.NewRuleTooltip_1=Clear the rule editor to begin a new rule FileExporterSettingsPanel.NewRuleTooltip_1=Clear the rule editor to begin a new rule
FileExporterSettingsPanel.DeleteTooltip_1=Delete the selected rule FileExporterSettingsPanel.DeleteTooltip_1=Delete the selected rule
FileExporterSettingsPanel.SaveTooltip_1=Save the current rule FileExporterSettingsPanel.SaveTooltip_1=Save the current rule
AutoIngestCasePanel.rbDays.text=Days
AutoIngestCasePanel.rbWeeks.text=Weeks
AutoIngestCasePanel.rbMonths.text=Months
AutoIngestCasePanel.rbAllCases.text=Everything
AutoIngestCasePanel.bnRefresh.text=&Refresh
AutoIngestCasePanel.bnOpen.text=&Open
AutoIngestCasePanel.bnShowLog.toolTipText=Display case log file for selected case
AutoIngestCasePanel.bnShowLog.text=&Show Log
AutoIngestCasePanel.rbGroupLabel.text=Show cases accessed in the last 10:
AutoIngestDashboard.refreshButton.toolTipText=Refresh displayed tables AutoIngestDashboard.refreshButton.toolTipText=Refresh displayed tables
AutoIngestDashboard.refreshButton.text=&Refresh AutoIngestDashboard.refreshButton.text=&Refresh
AutoIngestDashboard.jButton1.text=jButton1 AutoIngestDashboard.jButton1.text=jButton1
@ -247,6 +226,11 @@ AutoIngestDashboard.prioritizeJobButton.toolTipText=Move the selected job to the
AutoIngestDashboard.prioritizeJobButton.text=Prioritize &Job AutoIngestDashboard.prioritizeJobButton.text=Prioritize &Job
AutoIngestDashboard.prioritizeCaseButton.toolTipText=Move all images associated with a case to top of Pending queue. AutoIngestDashboard.prioritizeCaseButton.toolTipText=Move all images associated with a case to top of Pending queue.
AutoIngestDashboard.prioritizeCaseButton.text=Prioritize &Case AutoIngestDashboard.prioritizeCaseButton.text=Prioritize &Case
AutoIngestMetricsDialog.reportTextArea.text=
AutoIngestDashboard.clusterMetricsButton.text=Cluster Metrics
AutoIngestMetricsDialog.metricsButton.text=Get Metrics Since...
AutoIngestMetricsDialog.closeButton.text=Close
AutoIngestMetricsDialog.datePicker.toolTipText=Choose a date
ArchiveFilePanel.pathLabel.text=Browse for an archive file: ArchiveFilePanel.pathLabel.text=Browse for an archive file:
ArchiveFilePanel.browseButton.text=Browse ArchiveFilePanel.browseButton.text=Browse
ArchiveFilePanel.pathTextField.text= ArchiveFilePanel.pathTextField.text=

View File

@ -672,7 +672,6 @@ public class CaseImportPanel extends javax.swing.JPanel implements ImportDoneCal
*/ */
private void enableStartButton() { private void enableStartButton() {
if (UserPreferences.getIsMultiUserModeEnabled() if (UserPreferences.getIsMultiUserModeEnabled()
&& AutoIngestUserPreferences.getJoinAutoModeCluster()
&& (! RuntimeProperties.runningWithGUI()) && (! RuntimeProperties.runningWithGUI())
&& !tbCaseSource.getText().isEmpty() && !tbCaseSource.getText().isEmpty()
&& !tbCaseDestination.getText().isEmpty() && !tbCaseDestination.getText().isEmpty()

View File

@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.sleuthkit.autopsy.casemodule.CaseMetadata; import org.sleuthkit.autopsy.casemodule.CaseMetadata;
import org.sleuthkit.autopsy.coreutils.TimeStampUtils;
final class PathUtils { final class PathUtils {

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2015 Basis Technology Corp. * Copyright 2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -23,27 +23,34 @@ import javax.swing.ImageIcon;
import javax.swing.JTable; import javax.swing.JTable;
import static javax.swing.SwingConstants.CENTER; import static javax.swing.SwingConstants.CENTER;
import org.openide.util.ImageUtilities; import org.openide.util.ImageUtilities;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.guiutils.GrayableCellRenderer;
import org.sleuthkit.autopsy.guiutils.StatusIconCellRenderer;
/** /**
* A JTable cell renderer that represents an auto ingest alert file exists flag * A JTable cell renderer that represents whether the priority value of a job
* as a center-aligned icon, and grays out the cell if the table is disabled. * has ever been increased, tick if prioritized nothing if not.
*/ */
class CaseStatusIconCellRenderer extends GrayableCellRenderer { class PrioritizedIconCellRenderer extends GrayableCellRenderer {
@Messages({
"PrioritizedIconCellRenderer.prioritized.tooltiptext=This job has been prioritized. The most recently prioritized job should be processed next.",
"PrioritizedIconCellRenderer.notPrioritized.tooltiptext=This job has not been prioritized."
})
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
static final ImageIcon checkedIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/experimental/images/tick.png", false)); static final ImageIcon checkedIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/experimental/images/tick.png", false));
static final ImageIcon warningIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/experimental/images/warning16.png", false));
@Override @Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
setHorizontalAlignment(CENTER); setHorizontalAlignment(CENTER);
if ((value instanceof Boolean)) { if ((value instanceof Integer)) {
if (true == (Boolean) value) { if ((int) value == 0) {
setIcon(warningIcon); setIcon(null);
setToolTipText(org.openide.util.NbBundle.getMessage(CaseStatusIconCellRenderer.class, "CaseStatusIconCellRenderer.tooltiptext.warning")); setToolTipText(org.openide.util.NbBundle.getMessage(PrioritizedIconCellRenderer.class, "PrioritizedIconCellRenderer.notPrioritized.tooltiptext"));
} else { } else {
setIcon(checkedIcon); setIcon(checkedIcon);
setToolTipText(org.openide.util.NbBundle.getMessage(CaseStatusIconCellRenderer.class, "CaseStatusIconCellRenderer.tooltiptext.ok")); setToolTipText(org.openide.util.NbBundle.getMessage(PrioritizedIconCellRenderer.class, "PrioritizedIconCellRenderer.prioritized.tooltiptext"));
} }
} }
grayCellIfTableNotEnabled(table, isSelected); grayCellIfTableNotEnabled(table, isSelected);

View File

@ -47,6 +47,7 @@ import org.sleuthkit.autopsy.casemodule.SingleUserCaseConverter;
import org.sleuthkit.autopsy.casemodule.SingleUserCaseConverter.ImportCaseData; import org.sleuthkit.autopsy.casemodule.SingleUserCaseConverter.ImportCaseData;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.NetworkUtils; import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import org.sleuthkit.autopsy.coreutils.TimeStampUtils;
public class SingleUserCaseImporter implements Runnable { public class SingleUserCaseImporter implements Runnable {

View File

@ -2,20 +2,6 @@
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd"> <!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
<filesystem> <filesystem>
<!-- ======================================================
Actions
====================================================== -->
<folder name="Actions">
<folder name="Case">
<file name="org-sleuthkit-autopsy-experimental-autoingest-AutoIngestCaseOpenAction.instance">
<attr name="delegate" newvalue="org.sleuthkit.autopsy.experimental.autoingest.AutoIngestCaseOpenAction"/>
<attr name="displayName" stringvalue="Open Case"/>
<attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/>
<attr name="noIconInMenu" boolvalue="false"/>
</file>
</folder>
</folder>
<!-- ====================================================== <!-- ======================================================
Menu hidden Menu hidden
=========================================================== --> =========================================================== -->
@ -23,19 +9,12 @@
<folder name="Help"> <folder name="Help">
<file name="org-sleuthkit-autopsy-corecomponents-CustomAboutAction.shadow_hidden"/> <file name="org-sleuthkit-autopsy-corecomponents-CustomAboutAction.shadow_hidden"/>
</folder> </folder>
<folder name="Case"> </folder>
<file name="org-sleuthkit-autopsy-casemodule-CaseOpenAction.shadow_hidden"/>
<file name="org-sleuthkit-autopsy-experimental-autoingest-AutoIngestCaseOpenAction.shadow"> <folder name="Windows2">
<attr name="originalFile" stringvalue="Actions/Case/org-sleuthkit-autopsy-experimental-autoingest-AutoIngestCaseOpenAction.instance"/> <folder name="Modes">
<attr name="position" intvalue="101"/> <file name="dashboard.wsmode" url="dashboardWsmode.xml"/>
</file>
</folder> </folder>
</folder> </folder>
<folder name="Windows2">
<folder name="Modes">
<file name="dashboard.wsmode" url="dashboardWsmode.xml"/>
</folder>
</folder>
</filesystem> </filesystem>

View File

@ -1,10 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> <Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<NonVisualComponents>
<Component class="javax.swing.ButtonGroup" name="modeRadioButtons">
</Component>
</NonVisualComponents>
<AuxValues> <AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/> <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
@ -56,18 +52,71 @@
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Component id="cbJoinAutoIngestCluster" min="-2" pref="171" max="-2" attributes="0"/> <Component id="jLabelCurrentTask" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/> <EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="tbOops" min="-2" pref="465" max="-2" attributes="0"/> <Component id="jLabelTaskDescription" max="32767" attributes="0"/>
</Group> </Group>
<Group type="103" groupAlignment="0" max="-2" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Component id="jPanelNodeType" max="32767" attributes="0"/> <Group type="103" groupAlignment="1" attributes="0">
<Component id="jPanelSharedConfig" alignment="0" max="32767" attributes="0"/> <Component id="outputPathTextField" alignment="0" max="32767" attributes="0"/>
<Component id="jPanelIngestSettings" alignment="0" max="32767" attributes="0"/> <Component id="inputPathTextField" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="browseInputFolderButton" alignment="1" min="-2" max="-2" attributes="0"/>
<Component id="browseOutputFolderButton" alignment="1" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="jLabelSelectInputFolder" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="jLabelInvalidImageFolder" max="32767" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="uploadButton" alignment="0" min="-2" pref="143" max="-2" attributes="0"/>
<Component id="pbTaskInProgress" alignment="0" min="-2" pref="695" max="-2" attributes="0"/>
<Component id="masterNodeCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<Component id="cbJoinAutoIngestCluster" min="-2" pref="171" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="tbOops" min="-2" pref="465" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="bnEditIngestSettings" min="-2" pref="155" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="bnAdvancedSettings" min="-2" pref="155" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="bnFileExport" min="-2" pref="155" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="bnLogging" min="-2" pref="155" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="jLabelSelectOutputFolder" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="jLabelInvalidResultsFolder" min="-2" pref="544" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="sharedConfigCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="sharedSettingsErrorTextField" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="sharedSettingsTextField" min="-2" pref="400" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="browseSharedSettingsButton" min="-2" pref="143" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="downloadButton" min="-2" pref="143" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="configButtonErrorTextField" min="-2" pref="396" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="0" pref="32" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
<EmptySpace max="32767" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -79,542 +128,65 @@
<Component id="cbJoinAutoIngestCluster" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="cbJoinAutoIngestCluster" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="tbOops" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="tbOops" alignment="3" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/> <EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="jPanelNodeType" min="-2" max="-2" attributes="0"/> <Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabelSelectInputFolder" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabelInvalidImageFolder" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="inputPathTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="browseInputFolderButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="jPanelIngestSettings" min="-2" pref="62" max="-2" attributes="0"/> <Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabelSelectOutputFolder" alignment="3" min="-2" pref="21" max="-2" attributes="0"/>
<Component id="jLabelInvalidResultsFolder" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="browseOutputFolderButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="outputPathTextField" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="25" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="bnEditIngestSettings" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnFileExport" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnAdvancedSettings" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnLogging" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="sharedConfigCheckbox" alignment="3" min="-2" pref="21" max="-2" attributes="0"/>
<Component id="sharedSettingsErrorTextField" alignment="3" min="-2" pref="21" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="jPanelSharedConfig" max="32767" attributes="0"/> <Group type="103" groupAlignment="3" attributes="0">
<Component id="sharedSettingsTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="browseSharedSettingsButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="downloadButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="configButtonErrorTextField" alignment="3" min="-2" pref="21" max="-2" attributes="0"/>
</Group>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="masterNodeCheckBox" min="-2" pref="23" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="uploadButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabelCurrentTask" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabelTaskDescription" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="pbTaskInProgress" min="-2" pref="22" max="-2" attributes="0"/>
<EmptySpace pref="161" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
</Layout> </Layout>
<SubComponents> <SubComponents>
<Container class="javax.swing.JPanel" name="jPanelNodeType">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="Node Type Setup">
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
<EtchetBorder/>
</Border>
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.jPanelNodeType.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</TitledBorder>
</Border>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[50, 50]"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="1" attributes="0">
<Component id="outputPathTextField" alignment="0" max="32767" attributes="0"/>
<Component id="inputPathTextField" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="browseInputFolderButton" alignment="1" min="-2" max="-2" attributes="0"/>
<Component id="browseOutputFolderButton" alignment="1" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabelSelectMode" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jRadioButtonReview" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jRadioButtonAutomated" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="jLabelSelectInputFolder" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="jLabelInvalidImageFolder" max="32767" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Component id="jLabelSelectOutputFolder" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="jLabelInvalidResultsFolder" min="-2" pref="544" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" 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">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabelSelectMode" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="jRadioButtonAutomated" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jRadioButtonReview" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabelSelectInputFolder" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabelInvalidImageFolder" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="inputPathTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="browseInputFolderButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabelSelectOutputFolder" alignment="3" min="-2" pref="21" max="-2" attributes="0"/>
<Component id="jLabelInvalidResultsFolder" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="browseOutputFolderButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="outputPathTextField" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="jLabelSelectMode">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.jLabelSelectMode.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JRadioButton" name="jRadioButtonAutomated">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="modeRadioButtons"/>
</Property>
<Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.jRadioButtonAutomated.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/configuration/Bundle.properties" key="AutoIngestSettingsPanel.jRadioButtonAutomated.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="jRadioButtonAutomatedActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JRadioButton" name="jRadioButtonReview">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="modeRadioButtons"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.jRadioButtonReview.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/configuration/Bundle.properties" key="AutoIngestSettingsPanel.jRadioButtonReview.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="jRadioButtonReviewActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabelSelectInputFolder">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.jLabelSelectInputFolder.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="verticalAlignment" type="int" value="3"/>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="inputPathTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.inputPathTextField.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/configuration/Bundle.properties" key="AutoIngestSettingsPanel.inputPathTextField.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="browseInputFolderButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.browseInputFolderButton.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="browseInputFolderButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabelSelectOutputFolder">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.jLabelSelectOutputFolder.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="verticalAlignment" type="int" value="3"/>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="outputPathTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.outputPathTextField.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/configuration/Bundle.properties" key="AutoIngestSettingsPanel.outputPathTextField.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="browseOutputFolderButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.browseOutputFolderButton.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="browseOutputFolderButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabelInvalidImageFolder">
<Properties>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="0" green="0" red="ff" type="rgb"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.jLabelInvalidImageFolder.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabelInvalidResultsFolder">
<Properties>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="0" green="0" red="ff" type="rgb"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.jLabelInvalidResultsFolder.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/experimental/images/AIM.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="jPanelSharedConfig">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="Shared Configuration">
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
<EtchetBorder/>
</Border>
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.jPanelSharedConfig.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</TitledBorder>
</Border>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
<Component id="jLabelCurrentTask" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="jLabelTaskDescription" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="sharedSettingsTextField" min="-2" pref="400" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="browseSharedSettingsButton" min="-2" pref="143" max="-2" attributes="0"/>
</Group>
<Component id="uploadButton" alignment="0" min="-2" pref="143" max="-2" attributes="0"/>
<Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="downloadButton" min="-2" pref="143" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="configButtonErrorTextField" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="sharedConfigCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="sharedSettingsErrorTextField" max="32767" attributes="0"/>
</Group>
<Component id="jSeparator1" min="-2" pref="692" max="-2" attributes="0"/>
</Group>
<Component id="pbTaskInProgress" alignment="0" min="-2" pref="695" max="-2" attributes="0"/>
<Component id="masterNodeCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<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">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="sharedConfigCheckbox" alignment="3" min="-2" pref="21" max="-2" attributes="0"/>
<Component id="sharedSettingsErrorTextField" alignment="3" min="-2" pref="21" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="sharedSettingsTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="browseSharedSettingsButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="downloadButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="configButtonErrorTextField" alignment="3" min="-2" pref="21" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="jSeparator1" min="-2" pref="10" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
<Component id="masterNodeCheckBox" min="-2" pref="23" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="uploadButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabelCurrentTask" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabelTaskDescription" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="pbTaskInProgress" min="-2" pref="22" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JCheckBox" name="sharedConfigCheckbox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.sharedConfigCheckbox.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="[191, 14]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[191, 14]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[191, 14]"/>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="sharedConfigCheckboxItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JTextField" name="sharedSettingsTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.sharedSettingsTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="browseSharedSettingsButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.browseSharedSettingsButton.text" 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="browseSharedSettingsButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JTextField" name="sharedSettingsErrorTextField">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="0" green="0" red="ff" type="rgb"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.sharedSettingsErrorTextField.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="null"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="masterNodeCheckBox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.masterNodeCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="masterNodeCheckBoxItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="uploadButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.uploadButton.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="uploadButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="downloadButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.downloadButton.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="downloadButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabelCurrentTask">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.jLabelCurrentTask.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JProgressBar" name="pbTaskInProgress">
</Component>
<Component class="javax.swing.JLabel" name="jLabelTaskDescription">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.jLabelTaskDescription.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="configButtonErrorTextField">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="0" green="0" red="ff" type="rgb"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.configButtonErrorTextField.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="null"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JSeparator" name="jSeparator1">
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="jPanelIngestSettings">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="Automated Ingest Settings">
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
<EtchetBorder/>
</Border>
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.jPanelIngestSettings.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</TitledBorder>
</Border>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="bnEditIngestSettings" min="-2" pref="155" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="bnAdvancedSettings" min="-2" pref="155" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="bnFileExport" min="-2" pref="155" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="bnLogging" 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="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="bnEditIngestSettings" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnFileExport" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnAdvancedSettings" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnLogging" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JButton" name="bnEditIngestSettings">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.bnEditIngestSettings.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/configuration/Bundle.properties" key="AutoIngestSettingsPanel.bnEditIngestSettings.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="bnEditIngestSettingsActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="bnAdvancedSettings">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.bnAdvancedSettings.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="bnAdvancedSettingsActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="bnFileExport">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.bnFileExport.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="bnFileExportActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="bnLogging">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.bnLogging.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="bnLoggingActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JCheckBox" name="cbJoinAutoIngestCluster"> <Component class="javax.swing.JCheckBox" name="cbJoinAutoIngestCluster">
<Properties> <Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor"> <Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
@ -649,6 +221,238 @@
</Property> </Property>
</Properties> </Properties>
</Component> </Component>
<Component class="javax.swing.JButton" name="bnEditIngestSettings">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.bnEditIngestSettings.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/configuration/Bundle.properties" key="AutoIngestSettingsPanel.bnEditIngestSettings.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="bnEditIngestSettingsActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="bnAdvancedSettings">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.bnAdvancedSettings.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="bnAdvancedSettingsActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="bnFileExport">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.bnFileExport.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="bnFileExportActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="bnLogging">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.bnLogging.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="bnLoggingActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="browseOutputFolderButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.browseOutputFolderButton.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="browseOutputFolderButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="browseInputFolderButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.browseInputFolderButton.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="browseInputFolderButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JTextField" name="inputPathTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.inputPathTextField.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/configuration/Bundle.properties" key="AutoIngestSettingsPanel.inputPathTextField.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="outputPathTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.outputPathTextField.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/configuration/Bundle.properties" key="AutoIngestSettingsPanel.outputPathTextField.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabelInvalidResultsFolder">
<Properties>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="0" green="0" red="ff" type="rgb"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.jLabelInvalidResultsFolder.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabelInvalidImageFolder">
<Properties>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="0" green="0" red="ff" type="rgb"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.jLabelInvalidImageFolder.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabelSelectInputFolder">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.jLabelSelectInputFolder.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="verticalAlignment" type="int" value="3"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabelSelectOutputFolder">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.jLabelSelectOutputFolder.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="verticalAlignment" type="int" value="3"/>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="sharedConfigCheckbox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.sharedConfigCheckbox.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="[191, 14]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[191, 14]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[191, 14]"/>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="sharedConfigCheckboxItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JTextField" name="sharedSettingsErrorTextField">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="0" green="0" red="ff" type="rgb"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.sharedSettingsErrorTextField.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="null"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="sharedSettingsTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.sharedSettingsTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="browseSharedSettingsButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.browseSharedSettingsButton.text" 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="browseSharedSettingsButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="downloadButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.downloadButton.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="downloadButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JTextField" name="configButtonErrorTextField">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="0" green="0" red="ff" type="rgb"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.configButtonErrorTextField.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="null"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JProgressBar" name="pbTaskInProgress">
</Component>
<Component class="javax.swing.JLabel" name="jLabelTaskDescription">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.jLabelTaskDescription.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabelCurrentTask">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.jLabelCurrentTask.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="uploadButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.uploadButton.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="uploadButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="masterNodeCheckBox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.masterNodeCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="masterNodeCheckBoxItemStateChanged"/>
</Events>
</Component>
</SubComponents> </SubComponents>
</Container> </Container>
</SubComponents> </SubComponents>

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.experimental.configuration; package org.sleuthkit.autopsy.experimental.configuration;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.Cursor;
import java.io.File; import java.io.File;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.List; import java.util.List;
@ -56,7 +57,7 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
enum OptionsUiMode { enum OptionsUiMode {
STANDALONE, AIM, REVIEW, DOWNLOADING_CONFIGURATION STANDALONE, AIM, DOWNLOADING_CONFIGURATION
}; };
/** /**
@ -127,21 +128,10 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
if (inStartup) { if (inStartup) {
UserPreferences.SelectedMode storedMode = UserPreferences.getMode(); UserPreferences.SelectedMode storedMode = UserPreferences.getMode();
inputPathTextField.requestFocusInWindow(); inputPathTextField.requestFocusInWindow();
if (null != storedMode) { if (storedMode == UserPreferences.SelectedMode.AUTOINGEST) {
switch (storedMode) { enableOptionsBasedOnMode(OptionsUiMode.AIM);
case REVIEW: } else if (storedMode != null) {
jRadioButtonReview.setSelected(true); enableOptionsBasedOnMode(OptionsUiMode.STANDALONE);
enableOptionsBasedOnMode(OptionsUiMode.REVIEW);
break;
case AUTOINGEST:
jRadioButtonAutomated.setSelected(true);
enableOptionsBasedOnMode(OptionsUiMode.AIM);
break;
default:
cbJoinAutoIngestCluster.setSelected(false);
enableOptionsBasedOnMode(OptionsUiMode.STANDALONE);
break;
}
} }
} }
@ -207,22 +197,12 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
* Save mode to persistent storage. * Save mode to persistent storage.
*/ */
void store() { void store() {
boolean needsRestart = false; boolean needsRestart = (cbJoinAutoIngestCluster.isSelected() != AutoIngestUserPreferences.getJoinAutoModeCluster());
UserPreferences.SelectedMode storedMode = UserPreferences.getMode();
AutoIngestUserPreferences.setJoinAutoModeCluster(cbJoinAutoIngestCluster.isSelected()); AutoIngestUserPreferences.setJoinAutoModeCluster(cbJoinAutoIngestCluster.isSelected());
if (!cbJoinAutoIngestCluster.isSelected()) { if (!cbJoinAutoIngestCluster.isSelected()) {
if(storedMode == UserPreferences.SelectedMode.AUTOINGEST) {
needsRestart = true;
}
UserPreferences.setMode(UserPreferences.SelectedMode.STANDALONE); UserPreferences.setMode(UserPreferences.SelectedMode.STANDALONE);
} } else {
else if (jRadioButtonAutomated.isSelected()) {
if (storedMode == UserPreferences.SelectedMode.REVIEW) {
needsRestart = true;
}
UserPreferences.setMode(UserPreferences.SelectedMode.AUTOINGEST); UserPreferences.setMode(UserPreferences.SelectedMode.AUTOINGEST);
String imageFolderPath = getNormalizedFolderPath(inputPathTextField.getText().trim()); String imageFolderPath = getNormalizedFolderPath(inputPathTextField.getText().trim());
AutoIngestUserPreferences.setAutoModeImageFolder(imageFolderPath); AutoIngestUserPreferences.setAutoModeImageFolder(imageFolderPath);
@ -234,15 +214,8 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
AutoIngestUserPreferences.setSharedConfigFolder(globalSettingsPath); AutoIngestUserPreferences.setSharedConfigFolder(globalSettingsPath);
AutoIngestUserPreferences.setSharedConfigMaster(masterNodeCheckBox.isSelected()); AutoIngestUserPreferences.setSharedConfigMaster(masterNodeCheckBox.isSelected());
} }
} else if (jRadioButtonReview.isSelected()) {
if (storedMode == UserPreferences.SelectedMode.AUTOINGEST) {
needsRestart = true;
}
UserPreferences.setMode(UserPreferences.SelectedMode.REVIEW);
String resultsFolderPath = getNormalizedFolderPath(outputPathTextField.getText().trim());
AutoIngestUserPreferences.setAutoModeResultsFolder(resultsFolderPath);
} }
if (needsRestart) { if (needsRestart) {
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
JOptionPane.showMessageDialog(null, JOptionPane.showMessageDialog(null,
@ -306,23 +279,14 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
configButtonErrorTextField.setText("Shared configuration folder is invalid"); configButtonErrorTextField.setText("Shared configuration folder is invalid");
} }
break; break;
case REVIEW:
jLabelInvalidImageFolder.setVisible(false);
if (!validateResultsPath()) {
isValidNodePanel = false;
}
break;
case STANDALONE: case STANDALONE:
break; break;
default: default:
break; break;
} }
if (jRadioButtonAutomated.isSelected()) { if (sharedConfigCheckbox.isEnabled() && sharedConfigCheckbox.isSelected() && !validSharedConfigSettings()) {
if (sharedConfigCheckbox.isEnabled() && sharedConfigCheckbox.isSelected() && !validSharedConfigSettings()) { isValidNodePanel = false;
isValidNodePanel = false;
}
} }
return isValidNodePanel; return isValidNodePanel;
} }
@ -550,6 +514,7 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
} }
private void displayIngestJobSettingsPanel() { private void displayIngestJobSettingsPanel() {
this.getParent().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
IngestJobSettings ingestJobSettings = new IngestJobSettings(AutoIngestUserPreferences.getAutoModeIngestModuleContextString()); IngestJobSettings ingestJobSettings = new IngestJobSettings(AutoIngestUserPreferences.getAutoModeIngestModuleContextString());
showWarnings(ingestJobSettings); showWarnings(ingestJobSettings);
@ -563,6 +528,8 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
ingestJobSettings.save(); ingestJobSettings.save();
showWarnings(ingestJobSettings); showWarnings(ingestJobSettings);
} }
this.getParent().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
} }
private static void showWarnings(IngestJobSettings ingestJobSettings) { private static void showWarnings(IngestJobSettings ingestJobSettings) {
@ -579,24 +546,17 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
private void enableOptionsBasedOnMode(OptionsUiMode mode) { private void enableOptionsBasedOnMode(OptionsUiMode mode) {
if (mode != OptionsUiMode.DOWNLOADING_CONFIGURATION) { if (mode != OptionsUiMode.DOWNLOADING_CONFIGURATION) {
boolean nonMasterSharedConfig = !masterNodeCheckBox.isSelected() && sharedConfigCheckbox.isSelected(); boolean nonMasterSharedConfig = !masterNodeCheckBox.isSelected() && sharedConfigCheckbox.isSelected();
jRadioButtonAutomated.setEnabled(cbJoinAutoIngestCluster.isSelected());
jRadioButtonReview.setEnabled(cbJoinAutoIngestCluster.isSelected());
jLabelSelectInputFolder.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig); jLabelSelectInputFolder.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
inputPathTextField.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig); inputPathTextField.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
browseInputFolderButton.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig); browseInputFolderButton.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
jLabelSelectOutputFolder.setEnabled((mode == OptionsUiMode.AIM && !nonMasterSharedConfig) || mode == OptionsUiMode.REVIEW); jLabelSelectOutputFolder.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
outputPathTextField.setEnabled((mode == OptionsUiMode.AIM && !nonMasterSharedConfig) || mode == OptionsUiMode.REVIEW); outputPathTextField.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
browseOutputFolderButton.setEnabled((mode == OptionsUiMode.AIM && !nonMasterSharedConfig) || mode == OptionsUiMode.REVIEW); browseOutputFolderButton.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
jPanelSharedConfig.setEnabled(mode == OptionsUiMode.AIM);
jPanelIngestSettings.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
bnEditIngestSettings.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig); bnEditIngestSettings.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
bnAdvancedSettings.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig); bnAdvancedSettings.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
bnLogging.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig); bnLogging.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
jPanelSharedConfig.setEnabled(mode == OptionsUiMode.AIM);
sharedConfigCheckbox.setEnabled(mode == OptionsUiMode.AIM); sharedConfigCheckbox.setEnabled(mode == OptionsUiMode.AIM);
masterNodeCheckBox.setEnabled(mode == OptionsUiMode.AIM && sharedConfigCheckbox.isSelected()); masterNodeCheckBox.setEnabled(mode == OptionsUiMode.AIM && sharedConfigCheckbox.isSelected());
bnFileExport.setEnabled(mode == OptionsUiMode.AIM); bnFileExport.setEnabled(mode == OptionsUiMode.AIM);
@ -613,14 +573,8 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
private OptionsUiMode getModeFromRadioButtons() { private OptionsUiMode getModeFromRadioButtons() {
if (!cbJoinAutoIngestCluster.isSelected()) { if (!cbJoinAutoIngestCluster.isSelected()) {
return OptionsUiMode.STANDALONE; return OptionsUiMode.STANDALONE;
}
if (jRadioButtonAutomated.isSelected()) {
return OptionsUiMode.AIM;
} else if (jRadioButtonReview.isSelected()) {
return OptionsUiMode.REVIEW;
} else { } else {
return OptionsUiMode.STANDALONE; return OptionsUiMode.AIM;
} }
} }
@ -633,292 +587,51 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() { private void initComponents() {
modeRadioButtons = new javax.swing.ButtonGroup();
nodeScrollPane = new javax.swing.JScrollPane(); nodeScrollPane = new javax.swing.JScrollPane();
nodePanel = new javax.swing.JPanel(); nodePanel = new javax.swing.JPanel();
jPanelNodeType = new javax.swing.JPanel(); cbJoinAutoIngestCluster = new javax.swing.JCheckBox();
jLabelSelectMode = new javax.swing.JLabel(); tbOops = new javax.swing.JTextField();
jRadioButtonAutomated = new javax.swing.JRadioButton();
jRadioButtonReview = new javax.swing.JRadioButton();
jLabelSelectInputFolder = new javax.swing.JLabel();
inputPathTextField = new javax.swing.JTextField();
browseInputFolderButton = new javax.swing.JButton();
jLabelSelectOutputFolder = new javax.swing.JLabel();
outputPathTextField = new javax.swing.JTextField();
browseOutputFolderButton = new javax.swing.JButton();
jLabelInvalidImageFolder = new javax.swing.JLabel();
jLabelInvalidResultsFolder = new javax.swing.JLabel();
jLabel1 = new javax.swing.JLabel();
jPanelSharedConfig = new javax.swing.JPanel();
sharedConfigCheckbox = new javax.swing.JCheckBox();
sharedSettingsTextField = new javax.swing.JTextField();
browseSharedSettingsButton = new javax.swing.JButton();
sharedSettingsErrorTextField = new javax.swing.JTextField();
masterNodeCheckBox = new javax.swing.JCheckBox();
uploadButton = new javax.swing.JButton();
downloadButton = new javax.swing.JButton();
jLabelCurrentTask = new javax.swing.JLabel();
pbTaskInProgress = new javax.swing.JProgressBar();
jLabelTaskDescription = new javax.swing.JLabel();
configButtonErrorTextField = new javax.swing.JTextField();
jSeparator1 = new javax.swing.JSeparator();
jPanelIngestSettings = new javax.swing.JPanel();
bnEditIngestSettings = new javax.swing.JButton(); bnEditIngestSettings = new javax.swing.JButton();
bnAdvancedSettings = new javax.swing.JButton(); bnAdvancedSettings = new javax.swing.JButton();
bnFileExport = new javax.swing.JButton(); bnFileExport = new javax.swing.JButton();
bnLogging = new javax.swing.JButton(); bnLogging = new javax.swing.JButton();
cbJoinAutoIngestCluster = new javax.swing.JCheckBox(); browseOutputFolderButton = new javax.swing.JButton();
tbOops = new javax.swing.JTextField(); browseInputFolderButton = new javax.swing.JButton();
inputPathTextField = new javax.swing.JTextField();
outputPathTextField = new javax.swing.JTextField();
jLabelInvalidResultsFolder = new javax.swing.JLabel();
jLabelInvalidImageFolder = new javax.swing.JLabel();
jLabelSelectInputFolder = new javax.swing.JLabel();
jLabelSelectOutputFolder = new javax.swing.JLabel();
sharedConfigCheckbox = new javax.swing.JCheckBox();
sharedSettingsErrorTextField = new javax.swing.JTextField();
sharedSettingsTextField = new javax.swing.JTextField();
browseSharedSettingsButton = new javax.swing.JButton();
downloadButton = new javax.swing.JButton();
configButtonErrorTextField = new javax.swing.JTextField();
pbTaskInProgress = new javax.swing.JProgressBar();
jLabelTaskDescription = new javax.swing.JLabel();
jLabelCurrentTask = new javax.swing.JLabel();
uploadButton = new javax.swing.JButton();
masterNodeCheckBox = new javax.swing.JCheckBox();
nodeScrollPane.setMinimumSize(new java.awt.Dimension(0, 0)); nodeScrollPane.setMinimumSize(new java.awt.Dimension(0, 0));
nodePanel.setMinimumSize(new java.awt.Dimension(100, 100)); nodePanel.setMinimumSize(new java.awt.Dimension(100, 100));
jPanelNodeType.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jPanelNodeType.border.title"))); // NOI18N cbJoinAutoIngestCluster.setFont(cbJoinAutoIngestCluster.getFont().deriveFont(cbJoinAutoIngestCluster.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
jPanelNodeType.setMinimumSize(new java.awt.Dimension(50, 50)); org.openide.awt.Mnemonics.setLocalizedText(cbJoinAutoIngestCluster, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.cbJoinAutoIngestCluster.text")); // NOI18N
cbJoinAutoIngestCluster.addActionListener(new java.awt.event.ActionListener() {
org.openide.awt.Mnemonics.setLocalizedText(jLabelSelectMode, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelSelectMode.text")); // NOI18N
modeRadioButtons.add(jRadioButtonAutomated);
jRadioButtonAutomated.setSelected(true);
org.openide.awt.Mnemonics.setLocalizedText(jRadioButtonAutomated, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jRadioButtonAutomated.text")); // NOI18N
jRadioButtonAutomated.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jRadioButtonAutomated.toolTipText")); // NOI18N
jRadioButtonAutomated.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
jRadioButtonAutomatedActionPerformed(evt); cbJoinAutoIngestClusterActionPerformed(evt);
} }
}); });
modeRadioButtons.add(jRadioButtonReview); tbOops.setEditable(false);
org.openide.awt.Mnemonics.setLocalizedText(jRadioButtonReview, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jRadioButtonReview.text")); // NOI18N tbOops.setFont(tbOops.getFont().deriveFont(tbOops.getFont().getStyle() | java.awt.Font.BOLD, 12));
jRadioButtonReview.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jRadioButtonReview.toolTipText")); // NOI18N tbOops.setForeground(new java.awt.Color(255, 0, 0));
jRadioButtonReview.addActionListener(new java.awt.event.ActionListener() { tbOops.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.tbOops.text")); // NOI18N
public void actionPerformed(java.awt.event.ActionEvent evt) { tbOops.setBorder(null);
jRadioButtonReviewActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(jLabelSelectInputFolder, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelSelectInputFolder.text")); // NOI18N
jLabelSelectInputFolder.setVerticalAlignment(javax.swing.SwingConstants.BOTTOM);
inputPathTextField.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.inputPathTextField.text")); // NOI18N
inputPathTextField.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.inputPathTextField.toolTipText")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(browseInputFolderButton, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.browseInputFolderButton.text")); // NOI18N
browseInputFolderButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
browseInputFolderButtonActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(jLabelSelectOutputFolder, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelSelectOutputFolder.text")); // NOI18N
jLabelSelectOutputFolder.setVerticalAlignment(javax.swing.SwingConstants.BOTTOM);
outputPathTextField.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.outputPathTextField.text")); // NOI18N
outputPathTextField.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.outputPathTextField.toolTipText")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(browseOutputFolderButton, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.browseOutputFolderButton.text")); // NOI18N
browseOutputFolderButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
browseOutputFolderButtonActionPerformed(evt);
}
});
jLabelInvalidImageFolder.setForeground(new java.awt.Color(255, 0, 0));
org.openide.awt.Mnemonics.setLocalizedText(jLabelInvalidImageFolder, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelInvalidImageFolder.text")); // NOI18N
jLabelInvalidResultsFolder.setForeground(new java.awt.Color(255, 0, 0));
org.openide.awt.Mnemonics.setLocalizedText(jLabelInvalidResultsFolder, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelInvalidResultsFolder.text")); // NOI18N
jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/experimental/images/AIM.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabel1.text")); // NOI18N
javax.swing.GroupLayout jPanelNodeTypeLayout = new javax.swing.GroupLayout(jPanelNodeType);
jPanelNodeType.setLayout(jPanelNodeTypeLayout);
jPanelNodeTypeLayout.setHorizontalGroup(
jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelNodeTypeLayout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelNodeTypeLayout.createSequentialGroup()
.addGroup(jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(outputPathTextField, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(inputPathTextField, javax.swing.GroupLayout.Alignment.LEADING))
.addGap(10, 10, 10)
.addGroup(jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(browseInputFolderButton, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(browseOutputFolderButton, javax.swing.GroupLayout.Alignment.TRAILING)))
.addGroup(jPanelNodeTypeLayout.createSequentialGroup()
.addGroup(jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabelSelectMode)
.addComponent(jRadioButtonReview)
.addComponent(jRadioButtonAutomated))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jLabel1))
.addGroup(jPanelNodeTypeLayout.createSequentialGroup()
.addComponent(jLabelSelectInputFolder)
.addGap(18, 18, 18)
.addComponent(jLabelInvalidImageFolder, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(jPanelNodeTypeLayout.createSequentialGroup()
.addComponent(jLabelSelectOutputFolder)
.addGap(18, 18, 18)
.addComponent(jLabelInvalidResultsFolder, javax.swing.GroupLayout.PREFERRED_SIZE, 544, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
jPanelNodeTypeLayout.setVerticalGroup(
jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelNodeTypeLayout.createSequentialGroup()
.addGroup(jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelNodeTypeLayout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabelSelectMode)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jRadioButtonAutomated)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jRadioButtonReview))
.addComponent(jLabel1))
.addGap(1, 1, 1)
.addGroup(jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabelSelectInputFolder)
.addComponent(jLabelInvalidImageFolder))
.addGap(1, 1, 1)
.addGroup(jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(inputPathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(browseInputFolderButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabelSelectOutputFolder, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabelInvalidResultsFolder))
.addGap(1, 1, 1)
.addGroup(jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(browseOutputFolderButton)
.addComponent(outputPathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(0, 0, Short.MAX_VALUE))
);
jPanelSharedConfig.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jPanelSharedConfig.border.title"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(sharedConfigCheckbox, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.sharedConfigCheckbox.text")); // NOI18N
sharedConfigCheckbox.setMaximumSize(new java.awt.Dimension(191, 14));
sharedConfigCheckbox.setMinimumSize(new java.awt.Dimension(191, 14));
sharedConfigCheckbox.setPreferredSize(new java.awt.Dimension(191, 14));
sharedConfigCheckbox.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
sharedConfigCheckboxItemStateChanged(evt);
}
});
sharedSettingsTextField.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.sharedSettingsTextField.text")); // NOI18N
sharedSettingsTextField.setEnabled(false);
org.openide.awt.Mnemonics.setLocalizedText(browseSharedSettingsButton, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.browseSharedSettingsButton.text")); // NOI18N
browseSharedSettingsButton.setEnabled(false);
browseSharedSettingsButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
browseSharedSettingsButtonActionPerformed(evt);
}
});
sharedSettingsErrorTextField.setEditable(false);
sharedSettingsErrorTextField.setForeground(new java.awt.Color(255, 0, 0));
sharedSettingsErrorTextField.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.sharedSettingsErrorTextField.text")); // NOI18N
sharedSettingsErrorTextField.setBorder(null);
org.openide.awt.Mnemonics.setLocalizedText(masterNodeCheckBox, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.masterNodeCheckBox.text")); // NOI18N
masterNodeCheckBox.setEnabled(false);
masterNodeCheckBox.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
masterNodeCheckBoxItemStateChanged(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(uploadButton, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.uploadButton.text")); // NOI18N
uploadButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
uploadButtonActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(downloadButton, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.downloadButton.text")); // NOI18N
downloadButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
downloadButtonActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(jLabelCurrentTask, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelCurrentTask.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(jLabelTaskDescription, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelTaskDescription.text")); // NOI18N
configButtonErrorTextField.setEditable(false);
configButtonErrorTextField.setForeground(new java.awt.Color(255, 0, 0));
configButtonErrorTextField.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.configButtonErrorTextField.text")); // NOI18N
configButtonErrorTextField.setBorder(null);
javax.swing.GroupLayout jPanelSharedConfigLayout = new javax.swing.GroupLayout(jPanelSharedConfig);
jPanelSharedConfig.setLayout(jPanelSharedConfigLayout);
jPanelSharedConfigLayout.setHorizontalGroup(
jPanelSharedConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelSharedConfigLayout.createSequentialGroup()
.addGap(10, 10, 10)
.addComponent(jLabelCurrentTask)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jLabelTaskDescription, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
.addGroup(jPanelSharedConfigLayout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanelSharedConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelSharedConfigLayout.createSequentialGroup()
.addComponent(sharedSettingsTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 400, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(browseSharedSettingsButton, javax.swing.GroupLayout.PREFERRED_SIZE, 143, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(uploadButton, javax.swing.GroupLayout.PREFERRED_SIZE, 143, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(jPanelSharedConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanelSharedConfigLayout.createSequentialGroup()
.addComponent(downloadButton, javax.swing.GroupLayout.PREFERRED_SIZE, 143, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(configButtonErrorTextField))
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanelSharedConfigLayout.createSequentialGroup()
.addComponent(sharedConfigCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(sharedSettingsErrorTextField))
.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 692, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(pbTaskInProgress, javax.swing.GroupLayout.PREFERRED_SIZE, 695, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(masterNodeCheckBox))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
jPanelSharedConfigLayout.setVerticalGroup(
jPanelSharedConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelSharedConfigLayout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanelSharedConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(sharedConfigCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(sharedSettingsErrorTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanelSharedConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(sharedSettingsTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(browseSharedSettingsButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(jPanelSharedConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(downloadButton)
.addComponent(configButtonErrorTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(1, 1, 1)
.addComponent(masterNodeCheckBox, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(uploadButton)
.addGap(8, 8, 8)
.addGroup(jPanelSharedConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabelCurrentTask)
.addComponent(jLabelTaskDescription))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(pbTaskInProgress, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
jPanelIngestSettings.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jPanelIngestSettings.border.title"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(bnEditIngestSettings, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.bnEditIngestSettings.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnEditIngestSettings, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.bnEditIngestSettings.text")); // NOI18N
bnEditIngestSettings.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.bnEditIngestSettings.toolTipText")); // NOI18N bnEditIngestSettings.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.bnEditIngestSettings.toolTipText")); // NOI18N
@ -949,46 +662,94 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
} }
}); });
javax.swing.GroupLayout jPanelIngestSettingsLayout = new javax.swing.GroupLayout(jPanelIngestSettings); org.openide.awt.Mnemonics.setLocalizedText(browseOutputFolderButton, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.browseOutputFolderButton.text")); // NOI18N
jPanelIngestSettings.setLayout(jPanelIngestSettingsLayout); browseOutputFolderButton.addActionListener(new java.awt.event.ActionListener() {
jPanelIngestSettingsLayout.setHorizontalGroup(
jPanelIngestSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelIngestSettingsLayout.createSequentialGroup()
.addContainerGap()
.addComponent(bnEditIngestSettings, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnAdvancedSettings, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnFileExport, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnLogging, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
jPanelIngestSettingsLayout.setVerticalGroup(
jPanelIngestSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelIngestSettingsLayout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanelIngestSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(bnEditIngestSettings)
.addComponent(bnFileExport)
.addComponent(bnAdvancedSettings)
.addComponent(bnLogging))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
cbJoinAutoIngestCluster.setFont(cbJoinAutoIngestCluster.getFont().deriveFont(cbJoinAutoIngestCluster.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
org.openide.awt.Mnemonics.setLocalizedText(cbJoinAutoIngestCluster, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.cbJoinAutoIngestCluster.text")); // NOI18N
cbJoinAutoIngestCluster.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
cbJoinAutoIngestClusterActionPerformed(evt); browseOutputFolderButtonActionPerformed(evt);
} }
}); });
tbOops.setEditable(false); org.openide.awt.Mnemonics.setLocalizedText(browseInputFolderButton, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.browseInputFolderButton.text")); // NOI18N
tbOops.setFont(tbOops.getFont().deriveFont(tbOops.getFont().getStyle() | java.awt.Font.BOLD, 12)); browseInputFolderButton.addActionListener(new java.awt.event.ActionListener() {
tbOops.setForeground(new java.awt.Color(255, 0, 0)); public void actionPerformed(java.awt.event.ActionEvent evt) {
tbOops.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.tbOops.text")); // NOI18N browseInputFolderButtonActionPerformed(evt);
tbOops.setBorder(null); }
});
inputPathTextField.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.inputPathTextField.text")); // NOI18N
inputPathTextField.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.inputPathTextField.toolTipText")); // NOI18N
outputPathTextField.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.outputPathTextField.text")); // NOI18N
outputPathTextField.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.outputPathTextField.toolTipText")); // NOI18N
jLabelInvalidResultsFolder.setForeground(new java.awt.Color(255, 0, 0));
org.openide.awt.Mnemonics.setLocalizedText(jLabelInvalidResultsFolder, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelInvalidResultsFolder.text")); // NOI18N
jLabelInvalidImageFolder.setForeground(new java.awt.Color(255, 0, 0));
org.openide.awt.Mnemonics.setLocalizedText(jLabelInvalidImageFolder, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelInvalidImageFolder.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(jLabelSelectInputFolder, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelSelectInputFolder.text")); // NOI18N
jLabelSelectInputFolder.setVerticalAlignment(javax.swing.SwingConstants.BOTTOM);
org.openide.awt.Mnemonics.setLocalizedText(jLabelSelectOutputFolder, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelSelectOutputFolder.text")); // NOI18N
jLabelSelectOutputFolder.setVerticalAlignment(javax.swing.SwingConstants.BOTTOM);
org.openide.awt.Mnemonics.setLocalizedText(sharedConfigCheckbox, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.sharedConfigCheckbox.text")); // NOI18N
sharedConfigCheckbox.setMaximumSize(new java.awt.Dimension(191, 14));
sharedConfigCheckbox.setMinimumSize(new java.awt.Dimension(191, 14));
sharedConfigCheckbox.setPreferredSize(new java.awt.Dimension(191, 14));
sharedConfigCheckbox.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
sharedConfigCheckboxItemStateChanged(evt);
}
});
sharedSettingsErrorTextField.setEditable(false);
sharedSettingsErrorTextField.setForeground(new java.awt.Color(255, 0, 0));
sharedSettingsErrorTextField.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.sharedSettingsErrorTextField.text")); // NOI18N
sharedSettingsErrorTextField.setBorder(null);
sharedSettingsTextField.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.sharedSettingsTextField.text")); // NOI18N
sharedSettingsTextField.setEnabled(false);
org.openide.awt.Mnemonics.setLocalizedText(browseSharedSettingsButton, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.browseSharedSettingsButton.text")); // NOI18N
browseSharedSettingsButton.setEnabled(false);
browseSharedSettingsButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
browseSharedSettingsButtonActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(downloadButton, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.downloadButton.text")); // NOI18N
downloadButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
downloadButtonActionPerformed(evt);
}
});
configButtonErrorTextField.setEditable(false);
configButtonErrorTextField.setForeground(new java.awt.Color(255, 0, 0));
configButtonErrorTextField.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.configButtonErrorTextField.text")); // NOI18N
configButtonErrorTextField.setBorder(null);
org.openide.awt.Mnemonics.setLocalizedText(jLabelTaskDescription, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelTaskDescription.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(jLabelCurrentTask, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelCurrentTask.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(uploadButton, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.uploadButton.text")); // NOI18N
uploadButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
uploadButtonActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(masterNodeCheckBox, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.masterNodeCheckBox.text")); // NOI18N
masterNodeCheckBox.setEnabled(false);
masterNodeCheckBox.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
masterNodeCheckBoxItemStateChanged(evt);
}
});
javax.swing.GroupLayout nodePanelLayout = new javax.swing.GroupLayout(nodePanel); javax.swing.GroupLayout nodePanelLayout = new javax.swing.GroupLayout(nodePanel);
nodePanel.setLayout(nodePanelLayout); nodePanel.setLayout(nodePanelLayout);
@ -998,14 +759,56 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
.addContainerGap() .addContainerGap()
.addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(nodePanelLayout.createSequentialGroup() .addGroup(nodePanelLayout.createSequentialGroup()
.addComponent(cbJoinAutoIngestCluster, javax.swing.GroupLayout.PREFERRED_SIZE, 171, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabelCurrentTask)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jLabelTaskDescription, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(nodePanelLayout.createSequentialGroup()
.addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(outputPathTextField, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(inputPathTextField, javax.swing.GroupLayout.Alignment.LEADING))
.addGap(10, 10, 10)
.addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(browseInputFolderButton, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(browseOutputFolderButton, javax.swing.GroupLayout.Alignment.TRAILING)))
.addGroup(nodePanelLayout.createSequentialGroup()
.addComponent(jLabelSelectInputFolder)
.addGap(18, 18, 18) .addGap(18, 18, 18)
.addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, 465, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(jLabelInvalidImageFolder, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup(nodePanelLayout.createSequentialGroup()
.addComponent(jPanelNodeType, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanelSharedConfig, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(uploadButton, javax.swing.GroupLayout.PREFERRED_SIZE, 143, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jPanelIngestSettings, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) .addComponent(pbTaskInProgress, javax.swing.GroupLayout.PREFERRED_SIZE, 695, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(masterNodeCheckBox)
.addGroup(nodePanelLayout.createSequentialGroup()
.addComponent(cbJoinAutoIngestCluster, javax.swing.GroupLayout.PREFERRED_SIZE, 171, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, 465, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(nodePanelLayout.createSequentialGroup()
.addComponent(bnEditIngestSettings, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnAdvancedSettings, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnFileExport, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnLogging, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(nodePanelLayout.createSequentialGroup()
.addComponent(jLabelSelectOutputFolder)
.addGap(18, 18, 18)
.addComponent(jLabelInvalidResultsFolder, javax.swing.GroupLayout.PREFERRED_SIZE, 544, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(nodePanelLayout.createSequentialGroup()
.addComponent(sharedConfigCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(sharedSettingsErrorTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(nodePanelLayout.createSequentialGroup()
.addComponent(sharedSettingsTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 400, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(browseSharedSettingsButton, javax.swing.GroupLayout.PREFERRED_SIZE, 143, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(nodePanelLayout.createSequentialGroup()
.addComponent(downloadButton, javax.swing.GroupLayout.PREFERRED_SIZE, 143, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(configButtonErrorTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 396, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(0, 32, Short.MAX_VALUE)))
.addContainerGap())
); );
nodePanelLayout.setVerticalGroup( nodePanelLayout.setVerticalGroup(
nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -1014,12 +817,51 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
.addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(cbJoinAutoIngestCluster) .addComponent(cbJoinAutoIngestCluster)
.addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(3, 3, 3) .addGap(18, 18, 18)
.addComponent(jPanelNodeType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabelSelectInputFolder)
.addComponent(jLabelInvalidImageFolder))
.addGap(1, 1, 1)
.addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(inputPathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(browseInputFolderButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanelIngestSettings, javax.swing.GroupLayout.PREFERRED_SIZE, 62, javax.swing.GroupLayout.PREFERRED_SIZE) .addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabelSelectOutputFolder, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabelInvalidResultsFolder))
.addGap(1, 1, 1)
.addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(browseOutputFolderButton)
.addComponent(outputPathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(25, 25, 25)
.addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(bnEditIngestSettings)
.addComponent(bnFileExport)
.addComponent(bnAdvancedSettings)
.addComponent(bnLogging))
.addGap(18, 18, 18)
.addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(sharedConfigCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(sharedSettingsErrorTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanelSharedConfig, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(sharedSettingsTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(browseSharedSettingsButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(downloadButton)
.addComponent(configButtonErrorTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18)
.addComponent(masterNodeCheckBox, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(uploadButton)
.addGap(8, 8, 8)
.addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabelCurrentTask)
.addComponent(jLabelTaskDescription))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(pbTaskInProgress, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(161, Short.MAX_VALUE))
); );
nodeScrollPane.setViewportView(nodePanel); nodeScrollPane.setViewportView(nodePanel);
@ -1039,31 +881,35 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
private void browseSharedSettingsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseSharedSettingsButtonActionPerformed
String oldText = sharedSettingsTextField.getText().trim();
// set the current directory of the FileChooser if the oldText is valid
File currentDir = new File(oldText);
if (currentDir.exists()) {
fc.setCurrentDirectory(currentDir);
}
fc.setDialogTitle("Select shared configuration folder:");
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int retval = fc.showOpenDialog(this);
if (retval == JFileChooser.APPROVE_OPTION) {
String path = fc.getSelectedFile().getPath();
sharedSettingsTextField.setText(path);
validateSettings();
controller.changed();
}
}//GEN-LAST:event_browseSharedSettingsButtonActionPerformed
boolean permissionsAppropriate(String path) { boolean permissionsAppropriate(String path) {
return FileUtil.hasReadWriteAccess(Paths.get(path)); return FileUtil.hasReadWriteAccess(Paths.get(path));
} }
private void setSharedConfigEnable() {
setEnabledStateForSharedConfiguration();
if (sharedConfigCheckbox.isEnabled() && sharedConfigCheckbox.isSelected()) {
sharedSettingsTextField.setEnabled(true);
browseSharedSettingsButton.setEnabled(true);
masterNodeCheckBox.setEnabled(true);
downloadButton.setEnabled(true);
validateSettings();
controller.changed();
} else {
sharedSettingsTextField.setEnabled(false);
browseSharedSettingsButton.setEnabled(false);
masterNodeCheckBox.setEnabled(false);
downloadButton.setEnabled(false);
sharedSettingsErrorTextField.setText("");
validateSettings();
controller.changed();
}
}
private void cbJoinAutoIngestClusterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbJoinAutoIngestClusterActionPerformed
enableOptionsBasedOnMode(getModeFromRadioButtons());
controller.changed();
}//GEN-LAST:event_cbJoinAutoIngestClusterActionPerformed
private void downloadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_downloadButtonActionPerformed private void downloadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_downloadButtonActionPerformed
// First save the shared config folder and solr settings to the properties // First save the shared config folder and solr settings to the properties
String globalSettingsPath = getNormalizedFolderPath(sharedSettingsTextField.getText().trim()); String globalSettingsPath = getNormalizedFolderPath(sharedSettingsTextField.getText().trim());
@ -1100,31 +946,6 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
} }
}//GEN-LAST:event_uploadButtonActionPerformed }//GEN-LAST:event_uploadButtonActionPerformed
private void sharedConfigCheckboxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_sharedConfigCheckboxItemStateChanged
// Enable the global settings text box and browse button iff the checkbox is checked and enabled
setSharedConfigEnable();
}//GEN-LAST:event_sharedConfigCheckboxItemStateChanged
private void setSharedConfigEnable() {
setEnabledStateForSharedConfiguration();
if (sharedConfigCheckbox.isEnabled() && sharedConfigCheckbox.isSelected() && jRadioButtonAutomated.isSelected()) {
sharedSettingsTextField.setEnabled(true);
browseSharedSettingsButton.setEnabled(true);
masterNodeCheckBox.setEnabled(true);
downloadButton.setEnabled(true);
validateSettings();
controller.changed();
} else {
sharedSettingsTextField.setEnabled(false);
browseSharedSettingsButton.setEnabled(false);
masterNodeCheckBox.setEnabled(false);
downloadButton.setEnabled(false);
sharedSettingsErrorTextField.setText("");
validateSettings();
controller.changed();
}
}
private void masterNodeCheckBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_masterNodeCheckBoxItemStateChanged private void masterNodeCheckBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_masterNodeCheckBoxItemStateChanged
// Enable the global settings text box and browse button iff the checkbox is checked and enabled // Enable the global settings text box and browse button iff the checkbox is checked and enabled
setEnabledStateForSharedConfiguration(); setEnabledStateForSharedConfiguration();
@ -1137,10 +958,31 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
} }
}//GEN-LAST:event_masterNodeCheckBoxItemStateChanged }//GEN-LAST:event_masterNodeCheckBoxItemStateChanged
private void cbJoinAutoIngestClusterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbJoinAutoIngestClusterActionPerformed private void browseSharedSettingsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseSharedSettingsButtonActionPerformed
enableOptionsBasedOnMode(getModeFromRadioButtons());
controller.changed(); String oldText = sharedSettingsTextField.getText().trim();
}//GEN-LAST:event_cbJoinAutoIngestClusterActionPerformed // set the current directory of the FileChooser if the oldText is valid
File currentDir = new File(oldText);
if (currentDir.exists()) {
fc.setCurrentDirectory(currentDir);
}
fc.setDialogTitle("Select shared configuration folder:");
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int retval = fc.showOpenDialog(this);
if (retval == JFileChooser.APPROVE_OPTION) {
String path = fc.getSelectedFile().getPath();
sharedSettingsTextField.setText(path);
validateSettings();
controller.changed();
}
}//GEN-LAST:event_browseSharedSettingsButtonActionPerformed
private void sharedConfigCheckboxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_sharedConfigCheckboxItemStateChanged
// Enable the global settings text box and browse button iff the checkbox is checked and enabled
setSharedConfigEnable();
}//GEN-LAST:event_sharedConfigCheckboxItemStateChanged
private void browseOutputFolderButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseOutputFolderButtonActionPerformed private void browseOutputFolderButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseOutputFolderButtonActionPerformed
String oldText = outputPathTextField.getText().trim(); String oldText = outputPathTextField.getText().trim();
@ -1182,24 +1024,6 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
} }
}//GEN-LAST:event_browseInputFolderButtonActionPerformed }//GEN-LAST:event_browseInputFolderButtonActionPerformed
private void jRadioButtonReviewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioButtonReviewActionPerformed
if (cbJoinAutoIngestCluster.isSelected()) {
enableOptionsBasedOnMode(OptionsUiMode.REVIEW);
setSharedConfigEnable();
validateSettings();
controller.changed();
}
}//GEN-LAST:event_jRadioButtonReviewActionPerformed
private void jRadioButtonAutomatedActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioButtonAutomatedActionPerformed
if (cbJoinAutoIngestCluster.isSelected()) {
enableOptionsBasedOnMode(OptionsUiMode.AIM);
setSharedConfigEnable();
validateSettings();
controller.changed();
}
}//GEN-LAST:event_jRadioButtonAutomatedActionPerformed
private void bnLoggingActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnLoggingActionPerformed private void bnLoggingActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnLoggingActionPerformed
JDialog jDialog = new JDialog(); JDialog jDialog = new JDialog();
NodeStatusLogPanel loggingPanel = new NodeStatusLogPanel(jDialog); NodeStatusLogPanel loggingPanel = new NodeStatusLogPanel(jDialog);
@ -1242,9 +1066,9 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
private void bnAdvancedSettingsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnAdvancedSettingsActionPerformed private void bnAdvancedSettingsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnAdvancedSettingsActionPerformed
AdvancedAutoIngestSettingsPanel advancedAutoIngestSettingsPanel = new AdvancedAutoIngestSettingsPanel(getModeFromRadioButtons()); AdvancedAutoIngestSettingsPanel advancedAutoIngestSettingsPanel = new AdvancedAutoIngestSettingsPanel(getModeFromRadioButtons());
if (JOptionPane.showConfirmDialog(null, advancedAutoIngestSettingsPanel, if (JOptionPane.showConfirmDialog(null, advancedAutoIngestSettingsPanel,
NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.AdvancedAutoIngestSettingsPanel.Title"), NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.AdvancedAutoIngestSettingsPanel.Title"),
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE) == JOptionPane.OK_OPTION) { JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE) == JOptionPane.OK_OPTION) {
advancedAutoIngestSettingsPanel.store(); advancedAutoIngestSettingsPanel.store();
} }
}//GEN-LAST:event_bnAdvancedSettingsActionPerformed }//GEN-LAST:event_bnAdvancedSettingsActionPerformed
@ -1349,7 +1173,7 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
} }
void setEnabledStateForSharedConfiguration() { void setEnabledStateForSharedConfiguration() {
if (jRadioButtonAutomated.isSelected() && cbJoinAutoIngestCluster.isSelected()) { if (cbJoinAutoIngestCluster.isSelected()) {
enableOptionsBasedOnMode(OptionsUiMode.AIM); enableOptionsBasedOnMode(OptionsUiMode.AIM);
} }
} }
@ -1361,19 +1185,13 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
bnLogging.setEnabled(enabled); bnLogging.setEnabled(enabled);
browseInputFolderButton.setEnabled(enabled); browseInputFolderButton.setEnabled(enabled);
browseOutputFolderButton.setEnabled(enabled); browseOutputFolderButton.setEnabled(enabled);
browseSharedSettingsButton.setEnabled(sharedConfigCheckbox.isSelected() && jRadioButtonAutomated.isSelected()); browseSharedSettingsButton.setEnabled(sharedConfigCheckbox.isSelected() && cbJoinAutoIngestCluster.isSelected());
configButtonErrorTextField.setEnabled(enabled); configButtonErrorTextField.setEnabled(enabled);
inputPathTextField.setEnabled(enabled); inputPathTextField.setEnabled(enabled);
jLabelInvalidImageFolder.setEnabled(enabled); jLabelInvalidImageFolder.setEnabled(enabled);
jLabelInvalidResultsFolder.setEnabled(enabled); jLabelInvalidResultsFolder.setEnabled(enabled);
jLabelSelectInputFolder.setEnabled(enabled); jLabelSelectInputFolder.setEnabled(enabled);
jLabelSelectMode.setEnabled(enabled);
jLabelSelectOutputFolder.setEnabled(enabled); jLabelSelectOutputFolder.setEnabled(enabled);
jPanelIngestSettings.setEnabled(enabled);
jPanelNodeType.setEnabled(enabled);
jPanelSharedConfig.setEnabled(enabled);
jRadioButtonAutomated.setEnabled(enabled);
jRadioButtonReview.setEnabled(enabled);
outputPathTextField.setEnabled(enabled); outputPathTextField.setEnabled(enabled);
} }
@ -1389,22 +1207,13 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
private javax.swing.JTextField configButtonErrorTextField; private javax.swing.JTextField configButtonErrorTextField;
private javax.swing.JButton downloadButton; private javax.swing.JButton downloadButton;
private javax.swing.JTextField inputPathTextField; private javax.swing.JTextField inputPathTextField;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabelCurrentTask; private javax.swing.JLabel jLabelCurrentTask;
private javax.swing.JLabel jLabelInvalidImageFolder; private javax.swing.JLabel jLabelInvalidImageFolder;
private javax.swing.JLabel jLabelInvalidResultsFolder; private javax.swing.JLabel jLabelInvalidResultsFolder;
private javax.swing.JLabel jLabelSelectInputFolder; private javax.swing.JLabel jLabelSelectInputFolder;
private javax.swing.JLabel jLabelSelectMode;
private javax.swing.JLabel jLabelSelectOutputFolder; private javax.swing.JLabel jLabelSelectOutputFolder;
private javax.swing.JLabel jLabelTaskDescription; private javax.swing.JLabel jLabelTaskDescription;
private javax.swing.JPanel jPanelIngestSettings;
private javax.swing.JPanel jPanelNodeType;
private javax.swing.JPanel jPanelSharedConfig;
private javax.swing.JRadioButton jRadioButtonAutomated;
private javax.swing.JRadioButton jRadioButtonReview;
private javax.swing.JSeparator jSeparator1;
private javax.swing.JCheckBox masterNodeCheckBox; private javax.swing.JCheckBox masterNodeCheckBox;
private javax.swing.ButtonGroup modeRadioButtons;
private javax.swing.JPanel nodePanel; private javax.swing.JPanel nodePanel;
private javax.swing.JScrollPane nodeScrollPane; private javax.swing.JScrollPane nodeScrollPane;
private javax.swing.JTextField outputPathTextField; private javax.swing.JTextField outputPathTextField;

View File

@ -23,12 +23,9 @@ AIMIngestSettingsPanel.lbSecondsBetweenJobs.toolTipText=Increase this value if d
AIMIngestSettingsPanel.spSecondsBetweenJobs.toolTipText=Increase this value if database locks cause problems. It gives a little more time for finalizing. AIMIngestSettingsPanel.spSecondsBetweenJobs.toolTipText=Increase this value if database locks cause problems. It gives a little more time for finalizing.
AutoIngestSettingsPanel.AdvancedAutoIngestSettingsPanel.Title=Advanced Settings AutoIngestSettingsPanel.AdvancedAutoIngestSettingsPanel.Title=Advanced Settings
AutoIngestSettingsPanel.browseGlobalSettingsButton.text=Browse AutoIngestSettingsPanel.browseGlobalSettingsButton.text=Browse
AutoIngestSettingsPanel.browseSharedSettingsButton.text=Browse
AutoIngestSettingsPanel.CannotAccess=Cannot access AutoIngestSettingsPanel.CannotAccess=Cannot access
AutoIngestSettingsPanel.cbJoinAutoIngestCluster.text=Join auto ingest cluster AutoIngestSettingsPanel.cbJoinAutoIngestCluster.text=Join auto ingest cluster
AutoIngestSettingsPanel.CheckPermissions=Check permissions. AutoIngestSettingsPanel.CheckPermissions=Check permissions.
AutoIngestSettingsPanel.configButtonErrorTextField.text=configButtonErrorTextField
AutoIngestSettingsPanel.downloadButton.text=Download Config
AutoIngestSettingsPanel.EmptySettingsDirectory=Enter path to settings directory AutoIngestSettingsPanel.EmptySettingsDirectory=Enter path to settings directory
AutoIngestSettingsPanel.ErrorSettingDefaultFolder=Error creating default folder AutoIngestSettingsPanel.ErrorSettingDefaultFolder=Error creating default folder
AutoIngestSettingsPanel.FileExportRules.text=File Export Rules AutoIngestSettingsPanel.FileExportRules.text=File Export Rules
@ -36,12 +33,8 @@ AutoIngestSettingsPanel.globalSettingsErrorTextField.text=
AutoIngestSettingsPanel.globalSettingsTextField.text= AutoIngestSettingsPanel.globalSettingsTextField.text=
AutoIngestSettingsPanel.ImageDirectoryUnspecified=Shared images folder must be set AutoIngestSettingsPanel.ImageDirectoryUnspecified=Shared images folder must be set
AutoIngestSettingsPanel.InvalidPortNumber=Invalid port number. AutoIngestSettingsPanel.InvalidPortNumber=Invalid port number.
AutoIngestSettingsPanel.jLabelCurrentTask.text=Current task:
AutoIngestSettingsPanel.jLabelTaskDescription.text=jLabel1
AutoIngestSettingsPanel.jPanelSharedConfig.border.title=Shared Configuration
AutoIngestSettingsPanel.jRadioButtonCopyFiles.text=File Copy mode AutoIngestSettingsPanel.jRadioButtonCopyFiles.text=File Copy mode
AutoIngestSettingsPanel.KeywordSearchNull=Cannot find Keyword Search service AutoIngestSettingsPanel.KeywordSearchNull=Cannot find Keyword Search service
AutoIngestSettingsPanel.masterNodeCheckBox.text=Use this node as a master node that can upload settings
AutoIngestSettingsPanel.MustRestart=Autopsy must be restarted for new configuration to take effect AutoIngestSettingsPanel.MustRestart=Autopsy must be restarted for new configuration to take effect
AutoIngestSettingsPanel.nodePanel.TabConstraints.tabTitle=Node Configuration AutoIngestSettingsPanel.nodePanel.TabConstraints.tabTitle=Node Configuration
AutoIngestSettingsPanel.NodeStatusLogging.text=Node Status Logging Settings AutoIngestSettingsPanel.NodeStatusLogging.text=Node Status Logging Settings
@ -49,11 +42,7 @@ AutoIngestSettingsPanel.PathInvalid=Path is not valid
AutoIngestSettingsPanel.restartRequiredLabel.text=Application restart required to take effect. AutoIngestSettingsPanel.restartRequiredLabel.text=Application restart required to take effect.
AutoIngestSettingsPanel.restartRequiredLabel.text=Application restart required AutoIngestSettingsPanel.restartRequiredLabel.text=Application restart required
AutoIngestSettingsPanel.ResultsDirectoryUnspecified=Shared cases folder must be set AutoIngestSettingsPanel.ResultsDirectoryUnspecified=Shared cases folder must be set
AutoIngestSettingsPanel.sharedConfigCheckbox.text=Use shared configuration in folder:
AutoIngestSettingsPanel.sharedSettingsErrorTextField.text=globalSettingsErrorTextField
AutoIngestSettingsPanel.sharedSettingsTextField.text=
AutoIngestSettingsPanel.tbOops.text= AutoIngestSettingsPanel.tbOops.text=
AutoIngestSettingsPanel.uploadButton.text=Save & Upload Config
AutoIngestSettingsPanel.validationErrMsg.incomplete=Fill in all values AutoIngestSettingsPanel.validationErrMsg.incomplete=Fill in all values
AutoIngestSettingsPanel.validationErrMsg.invalidDatabasePort=Invalid database port number AutoIngestSettingsPanel.validationErrMsg.invalidDatabasePort=Invalid database port number
AutoIngestSettingsPanel.validationErrMsg.invalidIndexingServerPort=Invalid Solr server port number AutoIngestSettingsPanel.validationErrMsg.invalidIndexingServerPort=Invalid Solr server port number
@ -119,8 +108,16 @@ AdvancedAutoIngestSettingsPanel.lbConcurrentJobsPerCase.toolTipText_1=A soft lim
AdvancedAutoIngestSettingsPanel.lbNumberOfThreads.toolTipText_1=The number of threads running file level ingest modules. AdvancedAutoIngestSettingsPanel.lbNumberOfThreads.toolTipText_1=The number of threads running file level ingest modules.
AdvancedAutoIngestSettingsPanel.numberOfFileIngestThreadsComboBox.toolTipText=The number of threads running file level ingest modules. AdvancedAutoIngestSettingsPanel.numberOfFileIngestThreadsComboBox.toolTipText=The number of threads running file level ingest modules.
NodeStatusLogPanel.tbDbName.toolTipText_1=Database name NodeStatusLogPanel.tbDbName.toolTipText_1=Database name
AutoIngestSettingsPanel.jPanelNodeType.border.title=Node Type Setup AutoIngestSettingsPanel.sharedSettingsTextField.text=
AutoIngestSettingsPanel.jLabel1.text= AutoIngestSettingsPanel.sharedConfigCheckbox.text=Use shared configuration in folder:
AutoIngestSettingsPanel.configButtonErrorTextField.text=configButtonErrorTextField
AutoIngestSettingsPanel.jLabelTaskDescription.text=jLabel1
AutoIngestSettingsPanel.jLabelCurrentTask.text=Current task:
AutoIngestSettingsPanel.downloadButton.text=Download Config
AutoIngestSettingsPanel.uploadButton.text=Save & Upload Config
AutoIngestSettingsPanel.masterNodeCheckBox.text=Use this node as a master node that can upload settings
AutoIngestSettingsPanel.sharedSettingsErrorTextField.text=globalSettingsErrorTextField
AutoIngestSettingsPanel.browseSharedSettingsButton.text=Browse
AutoIngestSettingsPanel.jLabelInvalidResultsFolder.text=jLabelInvalidResultsFolder AutoIngestSettingsPanel.jLabelInvalidResultsFolder.text=jLabelInvalidResultsFolder
AutoIngestSettingsPanel.jLabelInvalidImageFolder.text=jLabelInvalidImageFolder AutoIngestSettingsPanel.jLabelInvalidImageFolder.text=jLabelInvalidImageFolder
AutoIngestSettingsPanel.browseOutputFolderButton.text=Browse AutoIngestSettingsPanel.browseOutputFolderButton.text=Browse
@ -131,12 +128,6 @@ AutoIngestSettingsPanel.browseInputFolderButton.text=Browse
AutoIngestSettingsPanel.inputPathTextField.toolTipText=Input folder for automated processing, i.e., the location where input case folders will be created for ingest by automated processing mode AutoIngestSettingsPanel.inputPathTextField.toolTipText=Input folder for automated processing, i.e., the location where input case folders will be created for ingest by automated processing mode
AutoIngestSettingsPanel.inputPathTextField.text= AutoIngestSettingsPanel.inputPathTextField.text=
AutoIngestSettingsPanel.jLabelSelectInputFolder.text=Select shared images folder: AutoIngestSettingsPanel.jLabelSelectInputFolder.text=Select shared images folder:
AutoIngestSettingsPanel.jRadioButtonReview.toolTipText=Review cases created in automated processing mode
AutoIngestSettingsPanel.jRadioButtonReview.text=Examiner node
AutoIngestSettingsPanel.jRadioButtonAutomated.toolTipText=Automatically detect new data sources and create cases.
AutoIngestSettingsPanel.jRadioButtonAutomated.text=Auto ingest node (application restart required)
AutoIngestSettingsPanel.jLabelSelectMode.text=Select mode:
AutoIngestSettingsPanel.jPanelIngestSettings.border.title=Automated Ingest Settings
AutoIngestSettingsPanel.bnLogging.text=Node Status Logging AutoIngestSettingsPanel.bnLogging.text=Node Status Logging
AutoIngestSettingsPanel.bnFileExport.text=File Export Settings AutoIngestSettingsPanel.bnFileExport.text=File Export Settings
AutoIngestSettingsPanel.bnAdvancedSettings.text=Advanced Settings AutoIngestSettingsPanel.bnAdvancedSettings.text=Advanced Settings

View File

@ -1016,7 +1016,7 @@ public class SharedConfiguration {
// If a copy of the database is loaded, close it before deleting and copying. // If a copy of the database is loaded, close it before deleting and copying.
if (localDb.exists()) { if (localDb.exists()) {
List<HashDbManager.HashDb> hashDbs = HashDbManager.getInstance().getAllFileTypeHashSets(); List<HashDbManager.HashDb> hashDbs = HashDbManager.getInstance().getAllHashSets();
HashDbManager.HashDb matchingDb = null; HashDbManager.HashDb matchingDb = null;
for (HashDbManager.HashDb db : hashDbs) { for (HashDbManager.HashDb db : hashDbs) {
try { try {
@ -1122,7 +1122,7 @@ public class SharedConfiguration {
try { try {
HashDbManager hashDbManager = HashDbManager.getInstance(); HashDbManager hashDbManager = HashDbManager.getInstance();
hashDbManager.loadLastSavedConfiguration(); hashDbManager.loadLastSavedConfiguration();
for (HashDb hashDb : hashDbManager.getAllFileTypeHashSets()) { for (HashDbManager.HashDb hashDb : hashDbManager.getAllHashSets()) {
if (hashDb.hasIndexOnly()) { if (hashDb.hasIndexOnly()) {
results.add(hashDb.getIndexPath()); results.add(hashDb.getIndexPath());
} else { } else {

View File

@ -139,8 +139,31 @@ final class GlobalListSettingsPanel extends javax.swing.JPanel implements Option
@Override @Override
public void addPropertyChangeListener(PropertyChangeListener l) { public void addPropertyChangeListener(PropertyChangeListener l) {
super.addPropertyChangeListener(l); super.addPropertyChangeListener(l);
listsManagementPanel.addPropertyChangeListener(l); /*
editListPanel.addPropertyChangeListener(l); * There is at least one look and feel library that follows the bad
* practice of calling overrideable methods in a constructor, e.g.:
*
* at
* javax.swing.plaf.synth.SynthPanelUI.installListeners(SynthPanelUI.java:83)
* at
* javax.swing.plaf.synth.SynthPanelUI.installUI(SynthPanelUI.java:63)
* at javax.swing.JComponent.setUI(JComponent.java:666) at
* javax.swing.JPanel.setUI(JPanel.java:153) at
* javax.swing.JPanel.updateUI(JPanel.java:126) at
* javax.swing.JPanel.<init>(JPanel.java:86) at
* javax.swing.JPanel.<init>(JPanel.java:109) at
* javax.swing.JPanel.<init>(JPanel.java:117)
*
* When this happens, the following child components of this JPanel
* subclass have not been constructed yet, since this panel's
* constructor has not been called yet.
*/
if (null != listsManagementPanel) {
listsManagementPanel.addPropertyChangeListener(l);
}
if (null != editListPanel) {
editListPanel.addPropertyChangeListener(l);
}
} }
@Override @Override

View File

@ -52,9 +52,34 @@ final class KeywordSearchGlobalSettingsPanel extends IngestModuleGlobalSettingsP
@Override @Override
public void addPropertyChangeListener(PropertyChangeListener l) { public void addPropertyChangeListener(PropertyChangeListener l) {
super.addPropertyChangeListener(l); super.addPropertyChangeListener(l);
listsPanel.addPropertyChangeListener(l); /*
languagesPanel.addPropertyChangeListener(l); * There is at least one look and feel library that follows the bad
generalPanel.addPropertyChangeListener(l); * practice of calling overrideable methods in a constructor, e.g.:
*
* at
* javax.swing.plaf.synth.SynthPanelUI.installListeners(SynthPanelUI.java:83)
* at
* javax.swing.plaf.synth.SynthPanelUI.installUI(SynthPanelUI.java:63)
* at javax.swing.JComponent.setUI(JComponent.java:666) at
* javax.swing.JPanel.setUI(JPanel.java:153) at
* javax.swing.JPanel.updateUI(JPanel.java:126) at
* javax.swing.JPanel.<init>(JPanel.java:86) at
* javax.swing.JPanel.<init>(JPanel.java:109) at
* javax.swing.JPanel.<init>(JPanel.java:117)
*
* When this happens, the following child components of this JPanel
* subclass have not been constructed yet, since this panel's
* constructor has not been called yet.
*/
if (null != listsPanel) {
listsPanel.addPropertyChangeListener(l);
}
if (null != languagesPanel) {
languagesPanel.addPropertyChangeListener(l);
}
if (null != generalPanel) {
generalPanel.addPropertyChangeListener(l);
}
} }
@Override @Override