Merge remote-tracking branch 'upstream/develop' into 3210_enableNewDatabases

Conflicts:
	Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java
	Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java
This commit is contained in:
Ann Priestman 2017-11-20 13:42:54 -05:00
commit 22f057c009
196 changed files with 4588 additions and 3503 deletions

View File

@ -244,6 +244,46 @@
<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>
<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-dependencies>
<public-packages>
@ -269,6 +309,7 @@
<package>org.sleuthkit.autopsy.events</package>
<package>org.sleuthkit.autopsy.externalresults</package>
<package>org.sleuthkit.autopsy.filesearch</package>
<package>org.sleuthkit.autopsy.guiutils</package>
<package>org.sleuthkit.autopsy.ingest</package>
<package>org.sleuthkit.autopsy.keywordsearchservice</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_CaseCloseAct=Close Case
CTL_CaseNewAction=New Case...
CTL_CasePropertiesAction=Case Properties...
CTL_CaseNewAction=New Case
CTL_CasePropertiesAction=Case Properties
CTL_CaseDeleteAction=Delete Case
CTL_OpenAction=Open Case...
CTL_CaseOpenAction=Open Case
Menu/Case/OpenRecentCase=Open Recent Case
CTL_CaseDeleteAction=Delete Case
OpenIDE-Module-Name=Case
@ -210,11 +210,32 @@ CasePropertiesPanel.lbDbName.text=Database Name:
CasePropertiesPanel.lbDbType.text=Case Type:
CasePropertiesPanel.caseNumberLabel.text=Case Number:
LocalDiskPanel.changeDatabasePathCheckbox.text=Update case to use VHD file upon completion
CueBannerPanel.openAutoIngestCaseButton.text=
CueBannerPanel.openMultiUserCaseButton.text=
CueBannerPanel.openExistingCaseButton.text=
CueBannerPanel.openRecentCaseButton.text=
CueBannerPanel.createNewCaseButton.text=
CueBannerPanel.createNewCaseLabel.text=Create New Case
CueBannerPanel.openRecentCaseLabel.text=Open Recent 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_CaseCloseAct=\u30b1\u30fc\u30b9\u3092\u9589\u3058\u308b
CTL_CaseNewAction=\u65b0\u898f\u30b1\u30fc\u30b9...
CTL_CasePropertiesAction=\u30b1\u30fc\u30b9\u30d7\u30ed\u30d1\u30c6\u30a3...
CTL_CaseNewAction=\u65b0\u898f\u30b1\u30fc\u30b9
CTL_CasePropertiesAction=\u30b1\u30fc\u30b9\u30d7\u30ed\u30d1\u30c6\u30a3
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
CTL_CaseDeleteAction=\u30b1\u30fc\u30b9\u3092\u524a\u9664
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.openExistingCaseLabel.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.Messages;
import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
@ -45,13 +44,16 @@ import org.sleuthkit.autopsy.coreutils.Logger;
final class CaseDeleteAction extends CallableSystemAction {
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() {
putValue(Action.NAME, NbBundle.getMessage(CaseDeleteAction.class, "CTL_CaseDeleteAction"));
this.setEnabled(false);
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 {
get();
} 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(
null,
Bundle.Case_deleteCaseFailureMessageBox_message(ex.getLocalizedMessage()),
@ -108,7 +110,7 @@ final class CaseDeleteAction extends CallableSystemAction {
}.execute();
}
} 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
public String getName() {
return NbBundle.getMessage(CaseOpenAction.class, "CTL_OpenAction");
return NbBundle.getMessage(CaseOpenAction.class, "CTL_CaseOpenAction");
}
@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="openRecentCaseButton" alignment="2" min="-2" pref="70" 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>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" 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="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>
<Component id="closeButton" alignment="1" min="-2" pref="73" max="-2" attributes="0"/>
@ -66,9 +66,9 @@
</Group>
<EmptySpace max="32767" 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">
<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"/>
</Group>
</Group>
@ -216,13 +216,13 @@
<Property name="orientation" type="int" value="1"/>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="openAutoIngestCaseButton">
<Component class="javax.swing.JButton" name="openMultiUserCaseButton">
<Properties>
<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"/>
</Property>
<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 name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="null" type="code"/>
@ -237,18 +237,18 @@
</Property>
</Properties>
<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>
</Component>
<Component class="javax.swing.JLabel" name="openAutoIngestCaseLabel">
<Component class="javax.swing.JLabel" name="openMultiUserCaseLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<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>
</Property>
<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>
</Properties>
</Component>

View File

@ -26,14 +26,11 @@ import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.AutoIngestCasePanelInterface;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
/*
* 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 {
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
* method.
*/
private static JDialog recentCasesWindow;
private static JDialog autoIngestCasePanelWindow;
public static void closeOpenRecentCasesWindow() {
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() {
initComponents();
customizeComponents();
initRecentCasesWindow();
enableComponents();
}
@ -75,7 +63,7 @@ public class CueBannerPanel extends javax.swing.JPanel {
ImageIcon icon = new ImageIcon(cl.getResource(welcomeLogo));
autopsyLogo.setIcon(icon);
}
customizeComponents();
initRecentCasesWindow();
enableComponents();
}
@ -90,11 +78,6 @@ public class CueBannerPanel extends javax.swing.JPanel {
public void refresh() {
enableComponents();
}
private void customizeComponents() {
initRecentCasesWindow();
initAutoIngestCasesWindow();
}
private void initRecentCasesWindow() {
recentCasesWindow = new JDialog(
@ -118,39 +101,15 @@ public class CueBannerPanel extends javax.swing.JPanel {
recentCasesWindow.pack();
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() {
boolean enableOpenRecentCaseButton = (RecentCases.getInstance().getTotalRecentCases() > 0);
openRecentCaseButton.setEnabled(enableOpenRecentCaseButton);
openRecentCaseLabel.setEnabled(enableOpenRecentCaseButton);
boolean showOpenAutoIngestCaseButton = (UserPreferences.getMode() == UserPreferences.SelectedMode.REVIEW);
openAutoIngestCaseButton.setVisible(showOpenAutoIngestCaseButton);
openAutoIngestCaseLabel.setVisible(showOpenAutoIngestCaseButton);
boolean enableOpenMultiUserCaseButton = UserPreferences.getIsMultiUserModeEnabled();
openMultiUserCaseButton.setEnabled(enableOpenMultiUserCaseButton);
openMultiUserCaseLabel.setEnabled(enableOpenMultiUserCaseButton);
}
/**
@ -172,8 +131,8 @@ public class CueBannerPanel extends javax.swing.JPanel {
openExistingCaseLabel = new javax.swing.JLabel();
closeButton = new javax.swing.JButton();
jSeparator1 = new javax.swing.JSeparator();
openAutoIngestCaseButton = new javax.swing.JButton();
openAutoIngestCaseLabel = new javax.swing.JLabel();
openMultiUserCaseButton = new javax.swing.JButton();
openMultiUserCaseLabel = new javax.swing.JLabel();
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
@ -229,21 +188,21 @@ public class CueBannerPanel extends javax.swing.JPanel {
jSeparator1.setOrientation(javax.swing.SwingConstants.VERTICAL);
openAutoIngestCaseButton.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
openAutoIngestCaseButton.setBorder(null);
openAutoIngestCaseButton.setBorderPainted(false);
openAutoIngestCaseButton.setContentAreaFilled(false);
openAutoIngestCaseButton.setMargin(new java.awt.Insets(1, 1, 1, 1));
openAutoIngestCaseButton.setPreferredSize(new java.awt.Dimension(64, 64));
openAutoIngestCaseButton.addActionListener(new java.awt.event.ActionListener() {
openMultiUserCaseButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/casemodule/btn_icon_open_existing.png"))); // NOI18N
openMultiUserCaseButton.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.openMultiUserCaseButton.text")); // NOI18N
openMultiUserCaseButton.setBorder(null);
openMultiUserCaseButton.setBorderPainted(false);
openMultiUserCaseButton.setContentAreaFilled(false);
openMultiUserCaseButton.setMargin(new java.awt.Insets(1, 1, 1, 1));
openMultiUserCaseButton.setPreferredSize(new java.awt.Dimension(64, 64));
openMultiUserCaseButton.addActionListener(new java.awt.event.ActionListener() {
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));
openAutoIngestCaseLabel.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.openAutoIngestCaseLabel.text")); // NOI18N
openMultiUserCaseLabel.setFont(openMultiUserCaseLabel.getFont().deriveFont(openMultiUserCaseLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 13));
openMultiUserCaseLabel.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.openMultiUserCaseLabel.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
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(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(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)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(createNewCaseLabel)
.addComponent(openRecentCaseLabel)
.addComponent(openExistingCaseLabel)
.addComponent(openAutoIngestCaseLabel)))
.addComponent(openMultiUserCaseLabel)))
.addComponent(closeButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 73, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);
@ -290,9 +249,9 @@ public class CueBannerPanel extends javax.swing.JPanel {
.addComponent(openExistingCaseLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.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()
.addComponent(openAutoIngestCaseLabel)
.addComponent(openMultiUserCaseLabel)
.addGap(20, 20, 20))))
.addComponent(jSeparator1)
.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);
}//GEN-LAST:event_openRecentCaseButtonActionPerformed
private void openAutoIngestCaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openAutoIngestCaseButtonActionPerformed
autoIngestCasePanelWindow.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
autoIngestCasePanelWindow.setVisible(true);
}//GEN-LAST:event_openAutoIngestCaseButtonActionPerformed
private void openMultiUserCaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openMultiUserCaseButtonActionPerformed
MultiUserCasesDialog multiUserCaseWindow = MultiUserCasesDialog.getInstance();
multiUserCaseWindow.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
multiUserCaseWindow.setVisible(true);
}//GEN-LAST:event_openMultiUserCaseButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel autopsyLogo;
@ -327,8 +287,8 @@ public class CueBannerPanel extends javax.swing.JPanel {
private javax.swing.JButton createNewCaseButton;
private javax.swing.JLabel createNewCaseLabel;
private javax.swing.JSeparator jSeparator1;
private javax.swing.JButton openAutoIngestCaseButton;
private javax.swing.JLabel openAutoIngestCaseLabel;
private javax.swing.JButton openMultiUserCaseButton;
private javax.swing.JLabel openMultiUserCaseLabel;
private javax.swing.JButton openExistingCaseButton;
private javax.swing.JLabel openExistingCaseLabel;
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"/>
<EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
</Group>
<Component id="scrollPaneTable" pref="1007" max="32767" attributes="0"/>
<Component id="scrollPaneTable" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
@ -82,7 +82,7 @@
<Component class="javax.swing.JButton" name="bnOpen">
<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="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 name="enabled" type="boolean" value="false"/>
</Properties>
@ -99,11 +99,9 @@
<SubComponents>
<Component class="javax.swing.JTable" name="casesTable">
<Properties>
<Property name="autoCreateRowSorter" type="boolean" value="true"/>
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="caseTableModel" type="code"/>
</Property>
<Property name="autoResizeMode" type="int" value="4"/>
<Property name="rowHeight" type="int" value="20"/>
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
<JTableSelectionModel selectionMode="0"/>
@ -118,7 +116,7 @@
<Component class="javax.swing.JButton" name="bnRefresh">
<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="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>
</Properties>
<Events>
@ -153,7 +151,7 @@
</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/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>
</Properties>
<Events>
@ -165,10 +163,10 @@
<Component class="javax.swing.JButton" name="bnShowLog">
<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="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 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 name="enabled" type="boolean" value="false"/>
</Properties>
@ -182,7 +180,7 @@
<ComponentRef name="rbGroupHistoryLength"/>
</Property>
<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 name="name" type="java.lang.String" value="" noResource="true"/>
</Properties>
@ -196,7 +194,7 @@
<ComponentRef name="rbGroupHistoryLength"/>
</Property>
<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>
</Properties>
<Events>
@ -209,7 +207,7 @@
<ComponentRef name="rbGroupHistoryLength"/>
</Property>
<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>
</Properties>
<Events>
@ -222,7 +220,7 @@
<Font name="Tahoma" size="12" style="0"/>
</Property>
<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>
</Properties>
</Component>

View File

@ -16,52 +16,42 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.experimental.autoingest;
package org.sleuthkit.autopsy.casemodule;
import java.awt.Cursor;
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.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Date;
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 javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.CaseActionCancelledException;
import org.sleuthkit.autopsy.casemodule.CaseMetadata;
import org.sleuthkit.autopsy.casemodule.StartupWindowProvider;
import javax.swing.table.TableRowSorter;
import org.sleuthkit.autopsy.casemodule.MultiUserCaseManager.MultiUserCase;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.guiutils.LongDateCellRenderer;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.casemodule.AutoIngestCasePanelInterface;
import org.sleuthkit.autopsy.casemodule.CueBannerPanel;
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import org.sleuthkit.autopsy.experimental.configuration.StartupWindow;
import org.sleuthkit.autopsy.guiutils.GrayableCellRenderer;
import org.sleuthkit.autopsy.guiutils.StatusIconCellRenderer;
/**
* A panel that allows a user to open cases created by auto ingest.
*/
@ServiceProvider(service = AutoIngestCasePanelInterface.class)
public final class AutoIngestCasePanel extends JPanel implements AutoIngestCasePanelInterface {
final class MultiUserCasesPanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(AutoIngestCasePanel.class.getName());
private static final AutoIngestCase.LastAccessedDateDescendingComparator reverseDateModifiedComparator = new AutoIngestCase.LastAccessedDateDescendingComparator();
private static final Logger LOGGER = Logger.getLogger(MultiUserCasesPanel.class.getName());
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_MAX_WIDTH = 2000;
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_MAX_WIDTH = 250;
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
@ -82,11 +69,12 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
* TODO (RC): Consider unifying this stuff in an enum as in
* 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 CREATEDTIME_HEADER = org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.CreatedTimeHeaderText");
private static final String COMPLETEDTIME_HEADER = org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.LastAccessedTimeHeaderText");
private static final String STATUS_ICON_HEADER = org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.StatusIconHeaderText");
private static final String OUTPUT_FOLDER_HEADER = org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.OutputFolderHeaderText");
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(MultiUserCasesPanel.class, "ReviewModeCasePanel.CreatedTimeHeaderText");
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(MultiUserCasesPanel.class, "ReviewModeCasePanel.StatusIconHeaderText");
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 {
@ -94,51 +82,20 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
CREATEDTIME,
COMPLETEDTIME,
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 Path currentlySelectedCase = null;
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();
}
});
}
private JDialog parentDialog;
/**
* Constructs a panel that allows a user to open cases created by automated
* ingest.
*
* @param parent The parent dialog for this panel.
*/
public AutoIngestCasePanel(JDialog parent) {
init(parent);
}
public void init(JDialog parent) {
MultiUserCasesPanel(JDialog parentDialog) {
this.parentDialog = parentDialog;
caseTableModel = new DefaultTableModel(columnNames, 0) {
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) {
return false;
}
@Override
public Class<?> getColumnClass(int col) {
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 = casesTable.getColumn(STATUS_ICON_HEADER);
theColumn.setCellRenderer(new CaseStatusIconCellRenderer());
theColumn.setCellRenderer(new StatusIconCellRenderer());
theColumn.setMinWidth(STATUS_COL_MIN_WIDTH);
theColumn.setMaxWidth(STATUS_COL_MAX_WIDTH);
theColumn.setPreferredWidth(STATUS_COL_PREFERRED_WIDTH);
theColumn.setWidth(STATUS_COL_PREFERRED_WIDTH);
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
@ -203,75 +163,39 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
}
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
* refreshes the cases table.
*/
private void refreshCasesTable() {
void refresh() {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try {
currentlySelectedCase = getSelectedCase();
AutoIngestCaseManager manager = AutoIngestCaseManager.getInstance();
List<AutoIngestCase> theModel = manager.getCases();
EventQueue.invokeLater(new CaseTableRefreshTask(theModel));
} catch (Exception ex) {
logger.log(Level.SEVERE, "Unexpected exception in refreshCasesTable", ex); //NON-NLS
MultiUserCaseManager manager = MultiUserCaseManager.getInstance();
List<MultiUserCase> cases = manager.getCases();
cases.sort(REVERSE_DATE_MODIFIED_COMPARATOR);
caseTableModel.setRowCount(0);
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.
*/
private void setButtons() {
boolean enabled = casesTable.getSelectedRow() >= 0 && casesTable.getSelectedRow() < casesTable.getRowCount();
bnOpen.setEnabled(enabled);
bnShowLog.setEnabled(enabled);
boolean openEnabled = casesTable.getSelectedRow() >= 0 && casesTable.getSelectedRow() < casesTable.getRowCount();
bnOpen.setEnabled(openEnabled);
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.
*/
private void openCase(Path caseMetadataFilePath) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
AutoIngestCaseManager.getInstance().openCase(caseMetadataFilePath);
stopCasesTableRefreshes();
StartupWindowProvider.getInstance().close();
CueBannerPanel.closeAutoIngestCasesWindow();
return null;
try {
StartupWindowProvider.getInstance().close();
if (parentDialog != null) {
parentDialog.setVisible(false);
}
@Override
protected void done() {
try {
get();
} 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));
}
MultiUserCaseManager.getInstance().openCase(caseMetadataFilePath);
} catch (CaseActionException | MultiUserCaseManager.MultiUserCaseManagerException 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());
}
}.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) {
setButtons();
this.cases = cases;
RowSorter(M tModel) {
super(tModel);
}
/**
* @inheritDoc
*/
@Override
public void run() {
cases.sort(reverseDateModifiedComparator);
caseTableModel.setRowCount(0);
long now = new Date().getTime();
for (AutoIngestCase autoIngestCase : cases) {
if (passesTimeFilter(now, autoIngestCase.getLastAccessedDate().getTime())) {
caseTableModel.addRow(new Object[]{
autoIngestCase.getCaseName(),
autoIngestCase.getCreationDate(),
autoIngestCase.getLastAccessedDate(),
(AutoIngestCase.CaseStatus.OK != autoIngestCase.getStatus()),
autoIngestCase.getCaseDirectoryPath().toString()});
public void toggleSortOrder(int column) {
if (!this.getModel().getColumnClass(column).equals(Date.class)) {
super.toggleSortOrder(column); //if it isn't a date 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);
}
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
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.addActionListener(new java.awt.event.ActionListener() {
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.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
casesTable.setRowHeight(20);
casesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
casesTable.addMouseListener(new java.awt.event.MouseAdapter() {
@ -463,7 +390,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
});
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() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnRefreshActionPerformed(evt);
@ -472,7 +399,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
rbGroupHistoryLength.add(rbAllCases);
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() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
rbAllCasesItemStateChanged(evt);
@ -494,8 +421,8 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
.addComponent(rbAllCases))
);
org.openide.awt.Mnemonics.setLocalizedText(bnShowLog, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.bnShowLog.text")); // NOI18N
bnShowLog.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.bnShowLog.toolTipText")); // 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(MultiUserCasesPanel.class, "MultiUserCasesPanel.bnShowLog.toolTipText")); // NOI18N
bnShowLog.setEnabled(false);
bnShowLog.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
@ -504,7 +431,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
});
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.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
@ -513,7 +440,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
});
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() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
rbWeeksItemStateChanged(evt);
@ -521,7 +448,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
});
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() {
public void itemStateChanged(java.awt.event.ItemEvent 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
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);
this.setLayout(layout);
@ -556,7 +483,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(bnRefresh)
.addGap(4, 4, 4))
.addComponent(scrollPaneTable, javax.swing.GroupLayout.DEFAULT_SIZE, 1007, Short.MAX_VALUE))
.addComponent(scrollPaneTable))
.addContainerGap())
);
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
int modelRow = casesTable.convertRowIndexToModel(casesTable.getSelectedRow());
Path caseMetadataFilePath = Paths.get((String) caseTableModel.getValueAt(modelRow,
COLUMN_HEADERS.OUTPUTFOLDER.ordinal()),
caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.CASE.ordinal()) + CaseMetadata.getFileExtension());
openCase(caseMetadataFilePath);
String caseDirectory = (String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.OUTPUTFOLDER.ordinal());
Path caseMetadataFilePath = Paths.get(caseDirectory, (String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.METADATA_FILE.ordinal()));
new Thread(() -> {
openCase(caseMetadataFilePath);
}).start();
}//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
*/
private void bnRefreshActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bnRefreshActionPerformed
{//GEN-HEADEREND:event_bnRefreshActionPerformed
updateView();
}//GEN-LAST:event_bnRefreshActionPerformed
private void bnRefreshActionPerformed(java.awt.event.ActionEvent evt) {
refresh();
}
private void rbDaysItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbDaysItemStateChanged
private void rbDaysItemStateChanged(java.awt.event.ItemEvent evt) {
if (rbDays.isSelected()) {
updateView();
refresh();
}
}//GEN-LAST:event_rbDaysItemStateChanged
}
private void rbAllCasesItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbAllCasesItemStateChanged
if (rbAllCases.isSelected()) {
updateView();
refresh();
}
}//GEN-LAST:event_rbAllCasesItemStateChanged
private void rbMonthsItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbMonthsItemStateChanged
if (rbMonths.isSelected()) {
updateView();
refresh();
}
}//GEN-LAST:event_rbMonthsItemStateChanged
private void rbWeeksItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbWeeksItemStateChanged
if (rbWeeks.isSelected()) {
updateView();
refresh();
}
}//GEN-LAST:event_rbWeeksItemStateChanged
private void bnShowLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnShowLogActionPerformed
int selectedRow = casesTable.convertRowIndexToModel(casesTable.getSelectedRow());
int rowCount = casesTable.getRowCount();
if (selectedRow >= 0 && selectedRow < rowCount) {
String thePath = (String) caseTableModel.getValueAt(selectedRow, COLUMN_HEADERS.OUTPUTFOLDER.ordinal());
Path pathToLog = AutoIngestJobLogger.getLogPath(Paths.get(thePath));
Path pathToLog = getSelectedCaseLogFilePath();
if (pathToLog != null) {
try {
if (pathToLog.toFile().exists()) {
Desktop.getDesktop().edit(pathToLog.toFile());
} else {
JOptionPane.showMessageDialog(this, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "DisplayLogDialog.cannotFindLog"),
org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "DisplayLogDialog.unableToShowLogFile"), JOptionPane.ERROR_MESSAGE);
JOptionPane.showMessageDialog(this, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.cannotFindLog"),
org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.unableToShowLogFile"), JOptionPane.ERROR_MESSAGE);
}
} 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,
org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "DisplayLogDialog.cannotOpenLog"),
org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "DisplayLogDialog.unableToShowLogFile"),
org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.cannotOpenLog"),
org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.unableToShowLogFile"),
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
if (evt.getClickCount() == 2) {
int modelRow = casesTable.convertRowIndexToModel(casesTable.getSelectedRow());
Path caseMetadataFilePath = Paths.get((String) caseTableModel.getValueAt(modelRow,
COLUMN_HEADERS.OUTPUTFOLDER.ordinal()),
caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.CASE.ordinal()) + CaseMetadata.getFileExtension());
String caseDirectory = (String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.OUTPUTFOLDER.ordinal());
Path caseMetadataFilePath = Paths.get(caseDirectory, (String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.METADATA_FILE.ordinal()));
openCase(caseMetadataFilePath);
}
}//GEN-LAST:event_casesTableMouseClicked

View File

@ -34,7 +34,6 @@ import java.time.LocalDate;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
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
* @throws EamDbException
*/
@Override
public void deleteReferenceSet(int referenceSetID) throws EamDbException{
deleteReferenceSetFiles(referenceSetID);
deleteReferenceSetEntries(referenceSetID);
deleteReferenceSetEntry(referenceSetID);
}
@ -1277,7 +1276,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
preparedStatement.setInt(1, referenceSetID);
preparedStatement.executeUpdate();
} 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 {
EamDbUtil.closePreparedStatement(preparedStatement);
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
* @throws EamDbException
*/
private void deleteReferenceSetFiles(int referenceSetID) throws EamDbException{
private void deleteReferenceSetEntries(int referenceSetID) throws EamDbException{
Connection conn = connect();
PreparedStatement preparedStatement = null;
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));
try {
@ -1302,7 +1303,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
preparedStatement.setInt(1, referenceSetID);
preparedStatement.executeUpdate();
} 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 {
EamDbUtil.closePreparedStatement(preparedStatement);
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 hashSetName
* @param setName
* @param version
* @return true if a matching entry exists in the central repository
* @throws EamDbException
*/
@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);
if(refSet == null){
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 referenceSetID
* @return true if the hash is found in the reference set
* @throws EamDbException
*/
@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();
@ -1343,17 +1359,17 @@ public abstract class AbstractSqlEamDb implements EamDb {
ResultSet resultSet = null;
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 {
preparedStatement = conn.prepareStatement(String.format(sql, fileTableName));
preparedStatement.setString(1, hash);
preparedStatement.setString(1, value);
preparedStatement.setInt(2, referenceSetID);
resultSet = preparedStatement.executeQuery();
resultSet.next();
matchingInstances = resultSet.getLong(1);
} 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 {
EamDbUtil.closePreparedStatement(preparedStatement);
EamDbUtil.closeResultSet(resultSet);
@ -1372,7 +1388,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
* @return Global known status of the artifact
*/
@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
if (aType.getId() != CorrelationAttribute.FILES_TYPE_ID) {
@ -1521,30 +1537,6 @@ public abstract class AbstractSqlEamDb implements EamDb {
EamGlobalSet globalSet = getReferenceSetByID(referenceSetID);
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.
@ -1618,7 +1610,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
* @throws EamDbException
*/
@Override
public int newReferencelSet(EamGlobalSet eamGlobalSet) throws EamDbException {
public int newReferenceSet(EamGlobalSet eamGlobalSet) throws EamDbException {
Connection conn = connect();
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
* @param hashSetName
* Check whether a reference set with the given name/version is in the central repo.
* Used to check for name collisions when creating reference sets.
* @param referenceSetName
* @param version
* @return true if a matching set is found
* @throws EamDbException
*/
@Override
public boolean referenceSetExists(String hashSetName, String version) throws EamDbException{
public boolean referenceSetExists(String referenceSetName, String version) throws EamDbException{
Connection conn = connect();
PreparedStatement preparedStatement1 = null;
@ -1773,13 +1766,14 @@ public abstract class AbstractSqlEamDb implements EamDb {
try {
preparedStatement1 = conn.prepareStatement(sql1);
preparedStatement1.setString(1, hashSetName);
preparedStatement1.setString(1, referenceSetName);
preparedStatement1.setString(2, version);
resultSet = preparedStatement1.executeQuery();
return (resultSet.next());
} 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 {
EamDbUtil.closePreparedStatement(preparedStatement1);
EamDbUtil.closeResultSet(resultSet);

View File

@ -362,38 +362,51 @@ public interface EamDb {
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
* @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 hashSetName
* @param referenceSetName
* @param version
* @return true if a matching entry exists in the central repository
* @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
* @param hashSetName
* Check whether a reference set with the given name/version is in the central repo.
* Used to check for name collisions when creating reference sets.
* @param referenceSetName
* @param version
* @return true if a matching set is found
* @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 referenceSetID
* @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?
@ -403,7 +416,7 @@ public interface EamDb {
*
* @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
@ -472,20 +485,7 @@ public interface EamDb {
*
* @throws EamDbException
*/
int newReferencelSet(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;
int newReferenceSet(EamGlobalSet eamGlobalSet) throws EamDbException;
/**
* Get a global set by ID

View File

@ -19,7 +19,6 @@
package org.sleuthkit.autopsy.centralrepository.datamodel;
import java.time.LocalDate;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager;
import org.sleuthkit.datamodel.TskData;
/**
@ -61,6 +60,26 @@ public class EamGlobalSet {
LocalDate 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
@ -145,17 +164,6 @@ public class EamGlobalSet {
public void setFileKnownStatus(TskData.FileKnown 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

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
* @throws EamDbException
*/
@ -657,27 +657,28 @@ public class SqliteEamDb extends AbstractSqlEamDb {
* @return true if the hash is found in the reference set
*/
@Override
public boolean isHashInReferenceSet(String hash, int referenceSetID) throws EamDbException{
public boolean isValueInReferenceSet(String value, int referenceSetID, int correlationTypeID) throws EamDbException {
try{
acquireSharedLock();
return super.isHashInReferenceSet(hash, referenceSetID);
return super.isValueInReferenceSet(value, referenceSetID, correlationTypeID);
} finally {
releaseSharedLock();
}
}
/**
* Check whether a reference set with the given name/version is in the central repo
* @param hashSetName
* Check whether a reference set with the given name/version is in the central repo.
* Used to check for name collisions when creating reference sets.
* @param referenceSetName
* @param version
* @return true if a matching set is found
* @throws EamDbException
*/
@Override
public boolean referenceSetExists(String hashSetName, String version) throws EamDbException {
public boolean referenceSetExists(String referenceSetName, String version) throws EamDbException {
try{
acquireSharedLock();
return super.referenceSetExists(hashSetName, version);
return super.referenceSetExists(referenceSetName, version);
} finally {
releaseSharedLock();
}
@ -692,10 +693,10 @@ public class SqliteEamDb extends AbstractSqlEamDb {
* @return Global known status of the artifact
*/
@Override
public boolean isArtifactlKnownBadByReference(CorrelationAttribute.Type aType, String value) throws EamDbException {
public boolean isArtifactKnownBadByReference(CorrelationAttribute.Type aType, String value) throws EamDbException {
try{
acquireSharedLock();
return super.isArtifactlKnownBadByReference(aType, value);
return super.isArtifactKnownBadByReference(aType, value);
} finally {
releaseSharedLock();
}
@ -785,10 +786,10 @@ public class SqliteEamDb extends AbstractSqlEamDb {
* @throws EamDbException
*/
@Override
public int newReferencelSet(EamGlobalSet eamGlobalSet) throws EamDbException {
public int newReferenceSet(EamGlobalSet eamGlobalSet) throws EamDbException {
try{
acquireExclusiveLock();
return super.newReferencelSet(eamGlobalSet);
return super.newReferenceSet(eamGlobalSet);
} finally {
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 javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javax.swing.SwingWorker;
import org.openide.LifecycleManager;
import org.openide.modules.ModuleInstall;
import org.openide.util.NbBundle;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.actions.IngestRunningCheck;
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.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
/**
@ -206,6 +206,9 @@ public class Installer extends ModuleInstall {
// Prevent the Autopsy UI from shrinking on high DPI displays
System.setProperty("sun.java2d.dpiaware", "false");
System.setProperty("prism.allowhidpi", "false");
// Update existing configuration in case of unsupported settings
updateConfig();
packageInstallers = new ArrayList<>();
packageInstallers.add(org.sleuthkit.autopsy.coreutils.Installer.getDefault());
@ -214,6 +217,21 @@ public class Installer extends ModuleInstall {
packageInstallers.add(org.sleuthkit.autopsy.ingest.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

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2014 Basis Technology Corp.
* Copyright 2014-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* 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 java.util.prefs.PreferenceChangeListener;
import java.util.prefs.Preferences;
import org.openide.util.Exceptions;
import org.openide.util.NbPreferences;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
@ -76,8 +75,7 @@ public final class UserPreferences {
public enum SelectedMode {
STANDALONE,
AUTOINGEST,
REVIEW
AUTOINGEST
};
/**

View File

@ -51,7 +51,7 @@
<file name="org-sleuthkit-autopsy-casemodule-CaseDeleteAction.instance"/>
<file name="org-sleuthkit-autopsy-casemodule-CaseOpenAction.instance">
<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="noIconInMenu" boolvalue="false"/>
</file>
@ -157,7 +157,7 @@
<attr name="position" intvalue="101"/>
</file>
<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"/>
<file name="org-sleuthkit-autopsy-casemodule-RecentCasesAction.shadow">
<attr name="originalFile" stringvalue="Actions/Case/org-sleuthkit-autopsy-casemodule-RecentCases.instance"/>
@ -165,11 +165,11 @@
</folder>
<file name="org-sleuthkit-autopsy-casemodule-CaseCloseAct.shadow">
<attr name="originalFile" stringvalue="Actions/Case/org-sleuthkit-autopsy-casemodule-CaseCloseAction.instance"/>
<attr name="position" intvalue="103"/>
<attr name="position" intvalue="104"/>
</file>
<file name="org-sleuthkit-autopsy-casemodule-CaseDeleteAction.shadow">
<attr name="originalFile" stringvalue="Actions/Case/org-sleuthkit-autopsy-casemodule-CaseDeleteAction.instance"/>
<attr name="position" intvalue="104"/>
<attr name="position" intvalue="105"/>
</file>
<file name="org-sleuthkit-autopsy-casemodule-AddImage-separatorBefore.instance">
<attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>

View File

@ -24,7 +24,10 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
/**
* Additional functionality of viewers supporting black board results such as
* the directory tree
*
*@deprecated No longer used.
*/
@Deprecated
public interface BlackboardResultViewer {
public static final String FINISHED_DISPLAY_EVT = "FINISHED_DISPLAY_EVT"; //NON-NLS

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 Basis Technology Corp.
* Copyright 2015-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.experimental.autoingest;
package org.sleuthkit.autopsy.coreutils;
import java.text.SimpleDateFormat;
import java.util.Calendar;
@ -24,32 +24,32 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Utility methods for working with strings with the time-stamp suffixes used by
* auto ingest.
* Utility methods for working with time stamps of the form
* 'yyyy_MM_dd_HH_mm_ss'.
*/
public final class TimeStampUtils {
/*
* 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 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.
*
* @return True or false.
*/
public static boolean endsWithTimeStamp(String inputString) {
Matcher m = timeStampPattern.matcher(inputString);
Matcher m = TIME_STAMP_PATTERN.matcher(inputString);
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.
*/
@ -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.
*/
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.
*
@ -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
*

View File

@ -43,9 +43,7 @@ public interface AutoIngestDataSourceProcessor extends DataSourceProcessor {
* or less means the data source is not supported by the
* DataSourceProcessor. Value of 100 indicates high certainty in
* being able to process the data source.
*
* @throws
* org.sleuthkit.autopsy.corecomponentinterfaces.AutomatedIngestDataSourceProcessor.AutomatedIngestDataSourceProcessorException
* @throws org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
*/
int canProcess(Path dataSourcePath) throws AutoIngestDataSourceProcessorException;
@ -65,9 +63,7 @@ public interface AutoIngestDataSourceProcessor extends DataSourceProcessor {
* background task to report progress.
* @param callBack Callback that will be used by the background task
* to return results.
*
* @throws
* org.sleuthkit.autopsy.corecomponentinterfaces.AutomatedIngestDataSourceProcessor.AutomatedIngestDataSourceProcessorException
* @throws org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
*/
void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) throws AutoIngestDataSourceProcessorException;

View File

@ -59,8 +59,6 @@ DirectoryTreeFilterNode.action.collapseAll.text=Collapse All
DirectoryTreeFilterNode.action.openFileSrcByAttr.text=Open File Search by Attributes
DirectoryTreeFilterNode.action.runIngestMods.text=Run Ingest Modules
DirectoryTreeTopComponent.action.viewArtContent.text=View Artifact Content
DirectoryTreeTopComponent.moduleErr=Module Error
DirectoryTreeTopComponent.moduleErr.msg=A module caused an error listening to DirectoryTreeTopComponent updates. See log to determine which module. Some data could be incomplete.
DirectoryTreeTopComponent.showRejectedCheckBox.text=Show Rejected Results
ExplorerNodeActionVisitor.action.imgDetails.title=Image Details
ExplorerNodeActionVisitor.action.extUnallocToSingleFiles=Extract Unallocated Space to Single Files

View File

@ -56,8 +56,6 @@ DataResultFilterNode.action.viewInDir.text=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\
DirectoryTreeFilterNode.action.openFileSrcByAttr.text=\u5c5e\u6027\u306b\u3088\u308b\u30d5\u30a1\u30a4\u30eb\u691c\u7d22\u3092\u958b\u304f
DirectoryTreeFilterNode.action.runIngestMods.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u5b9f\u884c
DirectoryTreeTopComponent.action.viewArtContent.text=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30b3\u30f3\u30c6\u30f3\u30c4\u3092\u8868\u793a
DirectoryTreeTopComponent.moduleErr=\u30e2\u30b8\u30e5\u30fc\u30eb\u30a8\u30e9\u30fc
DirectoryTreeTopComponent.moduleErr.msg=DirectoryTreeTopComponent\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u78ba\u8a8d\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u8d77\u3053\u3057\u307e\u3057\u305f\u3002\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304b\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u4e0d\u5b8c\u5168\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002
ExplorerNodeActionVisitor.action.imgDetails.title=\u30a4\u30e1\u30fc\u30b8\u8a73\u7d30
ExplorerNodeActionVisitor.action.extUnallocToSingleFiles=\u672a\u5272\u308a\u5f53\u3066\u9818\u57df\u5185\u306e\u30c7\u30fc\u30bf\u3092\u30b7\u30f3\u30b0\u30eb\u30d5\u30a1\u30a4\u30eb\u306b\u62bd\u51fa
ExplorerNodeActionVisitor.action.fileSystemDetails.title=\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u8a73\u7d30
@ -87,4 +85,4 @@ ExtractUnallocAction.done.notifyMsg.completedExtract.msg=\u30d5\u30a1\u30a4\u30e
ExtractUnallocAction.done.errMsg.title=\u62bd\u51fa\u30a8\u30e9\u30fc
ExtractUnallocAction.done.errMsg.msg=\u672a\u5272\u308a\u5f53\u3066\u9818\u57df\u3092\u62bd\u51fa\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a{0}
DirectoryTreeFilterNode.action.collapseAll.text=\u3059\u3079\u3066\u30b3\u30e9\u30d7\u30b9
ExtractAction.done.notifyMsg.extractErr=\u4e0b\u8a18\u306e\u30d5\u30a1\u30a4\u30eb\u306e\u62bd\u51fa\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a {0}
ExtractAction.done.notifyMsg.extractErr=\u4e0b\u8a18\u306e\u30d5\u30a1\u30a4\u30eb\u306e\u62bd\u51fa\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a {0}

View File

@ -27,7 +27,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@ -56,13 +55,11 @@ import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.core.RuntimeProperties;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.corecomponentinterfaces.BlackboardResultViewer;
import org.sleuthkit.autopsy.corecomponentinterfaces.CoreComponentControl;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataExplorer;
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.datamodel.ArtifactNodeSelectionInfo;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
import org.sleuthkit.autopsy.datamodel.CreditCards;
@ -99,7 +96,7 @@ import org.sleuthkit.datamodel.TskCoreException;
@Messages({
"DirectoryTreeTopComponent.resultsView.title=Listing"
})
public final class DirectoryTreeTopComponent extends TopComponent implements DataExplorer, ExplorerManager.Provider, BlackboardResultViewer {
public final class DirectoryTreeTopComponent extends TopComponent implements DataExplorer, ExplorerManager.Provider {
private final transient ExplorerManager em = new ExplorerManager();
private static DirectoryTreeTopComponent instance;
@ -851,7 +848,6 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
return false;
}
@Override
public void viewArtifact(final BlackboardArtifact art) {
int typeID = art.getArtifactTypeID();
String typeName = art.getArtifactTypeName();
@ -1064,28 +1060,14 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
// Another thread is needed because we have to wait for dataResult to populate
}
@Override
public void viewArtifactContent(BlackboardArtifact art) {
new ViewContextAction(
NbBundle.getMessage(this.getClass(), "DirectoryTreeTopComponent.action.viewArtContent.text"),
new BlackboardArtifactNode(art)).actionPerformed(null);
}
@Override
public void addOnFinishedListener(PropertyChangeListener l) {
DirectoryTreeTopComponent.this.addPropertyChangeListener(l);
}
void fireViewerComplete() {
try {
firePropertyChange(BlackboardResultViewer.FINISHED_DISPLAY_EVT, 0, 1);
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "DirectoryTreeTopComponent listener threw exception", e); //NON-NLS
MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "DirectoryTreeTopComponent.moduleErr"),
NbBundle.getMessage(this.getClass(),
"DirectoryTreeTopComponent.moduleErr.msg"),
MessageNotifyUtil.MessageType.ERROR);
}
}
}

View File

@ -3,7 +3,7 @@
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[750, 500]"/>
<Dimension value="[701, 453]"/>
</Property>
</Properties>
<AuxValues>
@ -32,19 +32,24 @@
</Layout>
<SubComponents>
<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>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" 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"/>
</Group>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" 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"/>
</Group>
</Group>
@ -55,7 +60,7 @@
<Group type="102" alignment="0" attributes="0">
<EmptySpace 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 type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
@ -81,13 +86,18 @@
<SubComponents>
<Container class="javax.swing.JSplitPane" name="jSplitPane1">
<Properties>
<Property name="dividerLocation" type="int" value="350"/>
<Property name="dividerLocation" type="int" value="365"/>
<Property name="dividerSize" type="int" value="1"/>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
<SubComponents>
<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>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="right"/>
@ -103,7 +113,7 @@
<Component id="exePathLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="exePathNameLabel" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="159" max="32767" attributes="0"/>
<EmptySpace pref="47" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -114,7 +124,7 @@
<Component id="exePathLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace 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>
</DimensionLayout>
@ -137,6 +147,11 @@
</SubComponents>
</Container>
<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>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="left"/>
@ -149,42 +164,35 @@
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="ruleListLabel" alignment="1" max="32767" attributes="0"/>
<Group type="102" 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="ruleListLabel" max="32767" attributes="0"/>
<Component id="rulesScrollPane" min="-2" pref="345" max="-2" attributes="0"/>
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="newRuleButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="editRuleButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="deleteRuleButton" min="-2" 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">
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="ruleListLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="rulesScrollPane" pref="380" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="rulesScrollPane" pref="328" max="32767" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" 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="deleteRuleButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -224,6 +232,15 @@
<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;)"/>
</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>
<Events>
<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">
<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 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>
<Events>
<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">
<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 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>
<Events>
<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();
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
jSplitPane1.setDividerLocation(350);
jSplitPane1.setDividerLocation(365);
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(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)
.addComponent(exePathLabel)
.addComponent(exePathNameLabel))
.addContainerGap(159, Short.MAX_VALUE))
.addContainerGap(47, Short.MAX_VALUE))
);
exePanelLayout.setVerticalGroup(
exePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -122,17 +126,22 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
.addComponent(exePathLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(exePathNameLabel)
.addContainerGap(408, Short.MAX_VALUE))
.addContainerGap(361, Short.MAX_VALUE))
);
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
rulesScrollPane.setViewportView(rulesList);
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
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() {
public void actionPerformed(java.awt.event.ActionEvent 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
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() {
public void actionPerformed(java.awt.event.ActionEvent 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
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() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
deleteRuleButtonActionPerformed(evt);
@ -162,20 +177,16 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
.addGroup(rulesPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(rulesPanelLayout.createSequentialGroup()
.addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(ruleListLabel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(rulesPanelLayout.createSequentialGroup()
.addComponent(rulesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 311, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
.addGroup(rulesPanelLayout.createSequentialGroup()
.addComponent(newRuleButton)
.addComponent(ruleListLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(rulesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 345, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, rulesPanelLayout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(newRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.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)
.addComponent(deleteRuleButton)
.addGap(0, 0, Short.MAX_VALUE))))
.addComponent(deleteRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap())
);
rulesPanelLayout.setVerticalGroup(
rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -183,12 +194,12 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
.addContainerGap()
.addComponent(ruleListLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(rulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(rulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 328, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(newRuleButton)
.addComponent(editRuleButton)
.addComponent(deleteRuleButton))
.addComponent(newRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(editRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(deleteRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);
@ -202,12 +213,12 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(externalViewerTitleLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 777, Short.MAX_VALUE)
.addComponent(externalViewerTitleLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 681, Short.MAX_VALUE)
.addContainerGap())
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 777, Short.MAX_VALUE)
.addComponent(jScrollPane1)
.addContainerGap()))
);
jPanel1Layout.setVerticalGroup(
@ -215,7 +226,7 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(externalViewerTitleLabel)
.addContainerGap(475, Short.MAX_VALUE))
.addContainerGap(428, Short.MAX_VALUE))
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGap(32, 32, 32)

View File

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

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 Basis Technology Corp.
* Copyright 2015-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -16,8 +16,9 @@
* See the License for the specific language governing permissions and
* 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.time.Duration;
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
* 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;
DurationCellRenderer() {
public DurationCellRenderer() {
setHorizontalAlignment(CENTER);
}
@ -71,4 +72,5 @@ class DurationCellRenderer extends GrayableCellRenderer {
grayCellIfTableNotEnabled(table, isSelected);
return this;
}
}

View File

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

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 Basis Technology Corp.
* Copyright 2015-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.experimental.autoingest;
package org.sleuthkit.autopsy.guiutils;
import java.awt.Component;
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
* table is disabled.
*/
class LongDateCellRenderer extends GrayableCellRenderer {
public class LongDateCellRenderer extends GrayableCellRenderer {
private static final long serialVersionUID = 1L;
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
* 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.text.SimpleDateFormat;
import javax.swing.JTable;
@ -46,4 +47,5 @@ class ShortDateCellRenderer extends GrayableCellRenderer {
grayCellIfTableNotEnabled(table, isSelected);
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

@ -21,14 +21,11 @@ package org.sleuthkit.autopsy.ingest;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JMenuItem;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;
import org.openide.util.Lookup;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.corecomponentinterfaces.BlackboardResultViewer;
import org.sleuthkit.autopsy.directorytree.DirectoryTreeTopComponent;
import org.sleuthkit.autopsy.ingest.IngestMessagePanel.IngestMessageGroup;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
@ -40,7 +37,8 @@ import org.sleuthkit.datamodel.TskException;
*/
class IngestMessageDetailsPanel extends javax.swing.JPanel {
private IngestMessageMainPanel mainPanel;
private final IngestMessageMainPanel mainPanel;
private final DirectoryTreeTopComponent dtc = DirectoryTreeTopComponent.findInstance();
/**
* Creates new form IngestMessageDetailsPanel
@ -69,18 +67,6 @@ class IngestMessageDetailsPanel extends javax.swing.JPanel {
styleSheet.addRule("td {white-space:pre-wrap;overflow:hidden;}"); //NON-NLS
styleSheet.addRule("th {font-weight:bold;}"); //NON-NLS
BlackboardResultViewer v = Lookup.getDefault().lookup(BlackboardResultViewer.class);
v.addOnFinishedListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(BlackboardResultViewer.FINISHED_DISPLAY_EVT)) {
artifactViewerFinished();
}
}
});
//right click
messageDetailsPane.setComponentPopupMenu(rightClickMenu);
ActionListener actList = new ActionListener() {
@ -193,11 +179,27 @@ class IngestMessageDetailsPanel extends javax.swing.JPanel {
}// </editor-fold>//GEN-END:initComponents
private void viewContentButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewContentButtonActionPerformed
viewContent(evt);
messageDetailsPane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
final IngestMessageGroup messageGroup = mainPanel.getMessagePanel().getSelectedMessage();
if (messageGroup != null) {
BlackboardArtifact art = messageGroup.getData();
if (art != null) {
dtc.viewArtifactContent(art);
}
}
messageDetailsPane.setCursor(null);
}//GEN-LAST:event_viewContentButtonActionPerformed
private void viewArtifactButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewArtifactButtonActionPerformed
viewArtifact(evt);
messageDetailsPane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
final IngestMessageGroup messageGroup = mainPanel.getMessagePanel().getSelectedMessage();
if (messageGroup != null) {
BlackboardArtifact art = messageGroup.getData();
if (art != null) {
dtc.viewArtifact(art);
}
}
messageDetailsPane.setCursor(null);
}//GEN-LAST:event_viewArtifactButtonActionPerformed
private void backButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_backButtonActionPerformed
@ -216,46 +218,6 @@ class IngestMessageDetailsPanel extends javax.swing.JPanel {
private javax.swing.JButton viewContentButton;
// End of variables declaration//GEN-END:variables
private void viewArtifact(java.awt.event.ActionEvent evt) {
artifactViewerInvoked();
final IngestMessageGroup messageGroup = mainPanel.getMessagePanel().getSelectedMessage();
if (messageGroup != null) {
BlackboardArtifact art = messageGroup.getData();
if (art != null) {
BlackboardResultViewer v = Lookup.getDefault().lookup(BlackboardResultViewer.class);
v.viewArtifact(art);
}
}
}
private void viewContent(java.awt.event.ActionEvent evt) {
artifactViewerInvoked();
final IngestMessageGroup messageGroup = mainPanel.getMessagePanel().getSelectedMessage();
if (messageGroup != null) {
BlackboardArtifact art = messageGroup.getData();
if (art != null) {
BlackboardResultViewer v = Lookup.getDefault().lookup(BlackboardResultViewer.class);
v.viewArtifactContent(art);
}
}
}
private void artifactViewerInvoked() {
//viewArtifactButton.setEnabled(false);
//viewContentButton.setEnabled(false);
messageDetailsPane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
}
private void artifactViewerFinished() {
//viewArtifactButton.setEnabled(true);
//viewContentButton.setEnabled(true);
messageDetailsPane.setCursor(null);
}
/**
* Display the details of a given message
*

View File

@ -140,9 +140,35 @@ public class IngestOptionsPanel extends IngestModuleGlobalSettingsPanel implemen
@Override
public void addPropertyChangeListener(PropertyChangeListener l) {
filterPanel.addPropertyChangeListener(l);
settingsPanel.addPropertyChangeListener(l);
profilePanel.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 != filterPanel) {
filterPanel.addPropertyChangeListener(l);
}
if (null != settingsPanel) {
settingsPanel.addPropertyChangeListener(l);
}
if (null != profilePanel) {
profilePanel.addPropertyChangeListener(l);
}
}
@Override

View File

@ -177,7 +177,29 @@ class ProfilePanel extends IngestModuleGlobalSettingsPanel {
@Override
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
private javax.swing.JPanel jPanel1;

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2014 Basis Technology Corp.
* Copyright 2013-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -19,66 +19,57 @@
package org.sleuthkit.autopsy.modules.embeddedfileextractor;
import java.io.File;
import java.util.logging.Level;
import java.nio.file.Paths;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.autopsy.ingest.FileIngestModule;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.autopsy.ingest.IngestModule.ProcessResult;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestMessage;
import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
import org.sleuthkit.autopsy.modules.embeddedfileextractor.ImageExtractor.SupportedImageExtractionFormats;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
import net.sf.sevenzipjbinding.SevenZipNativeInitializationException;
import org.sleuthkit.autopsy.ingest.FileIngestModuleAdapter;
/**
* Embedded File Extractor ingest module extracts embedded files from supported
* archives and documents, adds extracted embedded DerivedFiles, reschedules
* extracted DerivedFiles for ingest.
* A file level ingest module that extracts embedded files from supported
* archive and document formats.
*/
@NbBundle.Messages({
"CannotCreateOutputFolder=Unable to create output folder.",
"CannotRunFileTypeDetection=Unable to run file type detection.",
"UnableToInitializeLibraries=Unable to initialize 7Zip libraries."
})
public final class EmbeddedFileExtractorIngestModule implements FileIngestModule {
public final class EmbeddedFileExtractorIngestModule extends FileIngestModuleAdapter {
private static final Logger logger = Logger.getLogger(EmbeddedFileExtractorIngestModule.class.getName());
private final IngestServices services = IngestServices.getInstance();
static final String[] SUPPORTED_EXTENSIONS = {"zip", "rar", "arj", "7z", "7zip", "gzip", "gz", "bzip2", "tar", "tgz",}; // "iso"}; NON-NLS
private IngestJobContext context;
private long jobId;
private final static IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter();
private String moduleDirRelative;
private String moduleDirAbsolute;
private boolean archivextraction;
private boolean imageExtraction;
private ImageExtractor imageExtractor;
private SevenZipExtractor archiveExtractor;
SupportedImageExtractionFormats abstractFileExtractionFormat;
FileTypeDetector fileTypeDetector;
private FileTypeDetector fileTypeDetector;
/**
* Constructs a file level ingest module that extracts embedded files from
* supported archive and document formats.
*/
EmbeddedFileExtractorIngestModule() {
}
@Override
public void startUp(IngestJobContext context) throws IngestModuleException {
this.context = context;
jobId = context.getJobId();
/*
* Construct absolute and relative paths to the output directory. The
* relative path is relative to the case folder, and will be used in the
* case database for extracted (derived) file paths. The absolute path
* is used to write the extracted (derived) files to local storage.
*/
final Case currentCase = Case.getCurrentCase();
moduleDirRelative = Paths.get(currentCase.getModuleOutputDirectoryRelativePath(), EmbeddedFileExtractorModuleFactory.getModuleName()).toString();
moduleDirAbsolute = Paths.get(currentCase.getModuleDirectory(), EmbeddedFileExtractorModuleFactory.getModuleName()).toString();
moduleDirRelative = currentCase.getModuleOutputDirectoryRelativePath() + File.separator + EmbeddedFileExtractorModuleFactory.getModuleName(); //relative to the case, to store in db
moduleDirAbsolute = currentCase.getModuleDirectory() + File.separator + EmbeddedFileExtractorModuleFactory.getModuleName(); //absolute, to extract to
// initialize the folder where the embedded files are extracted.
/*
* Create the output directory.
*/
File extractionDirectory = new File(moduleDirAbsolute);
if (!extractionDirectory.exists()) {
try {
@ -88,71 +79,77 @@ public final class EmbeddedFileExtractorIngestModule implements FileIngestModule
}
}
// initialize the filetypedetector
/*
* Construct a file type detector.
*/
try {
fileTypeDetector = new FileTypeDetector();
} catch (FileTypeDetector.FileTypeDetectorInitException ex) {
throw new IngestModuleException(Bundle.CannotRunFileTypeDetection(), ex);
}
// initialize the extraction modules.
/*
* Construct a 7Zip file extractor for processing archive files.
*/
try {
this.archiveExtractor = new SevenZipExtractor(context, fileTypeDetector, moduleDirRelative, moduleDirAbsolute);
} catch (SevenZipNativeInitializationException ex) {
throw new IngestModuleException(Bundle.UnableToInitializeLibraries(), ex);
}
/*
* Construct an embedded images extractor for processing Microsoft
* Office documents.
*/
this.imageExtractor = new ImageExtractor(context, fileTypeDetector, moduleDirRelative, moduleDirAbsolute);
}
@Override
public ProcessResult process(AbstractFile abstractFile) {
// skip the unallocated blocks
if ((abstractFile.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)) ||
(abstractFile.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK))) {
/*
* Skip unallocated space files.
*/
if ((abstractFile.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS))
|| (abstractFile.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK))) {
return ProcessResult.OK;
}
// skip known files
/*
* Skip known files.
*/
if (abstractFile.getKnown().equals(TskData.FileKnown.KNOWN)) {
return ProcessResult.OK;
}
// check if the file is supported by either of the two embedded file extractors.
this.archivextraction = archiveExtractor.isSevenZipExtractionSupported(abstractFile);
this.imageExtraction = imageExtractor.isImageExtractionSupported(abstractFile);
if (!abstractFile.isFile() && (!this.archivextraction || !this.imageExtraction)) {
/*
* Skip directories, etc.
*/
if (!abstractFile.isFile()) {
return ProcessResult.OK;
}
// call the archive extractor if archiveExtraction flag is set.
if (this.archivextraction) {
/*
* Attempt embedded file extraction for the file if it is a supported
* type/format.
*/
if (archiveExtractor.isSevenZipExtractionSupported(abstractFile)) {
archiveExtractor.unpack(abstractFile);
}
// calling the image extractor if imageExtraction flag set.
if (this.imageExtraction) {
} else if (imageExtractor.isImageExtractionSupported(abstractFile)) {
imageExtractor.extractImage(abstractFile);
}
return ProcessResult.OK;
}
@Override
public void shutDown() {
// We don't need the value, but for cleanliness and consistency
refCounter.decrementAndGet(jobId);
/**
* Creates a unique name for a file by concatentating the file name and the
* file object id.
*
* @param file The file.
*
* @return The unique file name.
*/
static String getUniqueName(AbstractFile file) {
return file.getName() + "_" + file.getId();
}
/**
* Get local relative path to the unpacked archive root
*
* @param archiveFile
*
* @return
*/
static String getUniqueName(AbstractFile archiveFile) {
return archiveFile.getName() + "_" + archiveFile.getId();
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2014 Basis Technology Corp.
* Copyright 2014-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -27,8 +27,8 @@ import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
/**
* A factory for creating archive extractor file ingest modules and the user
* interface panels used to configure the settings for instances of the modules.
* A factory for creating file level ingest module that extracts embedded files
* from supported archive and document formats.
*/
@NbBundle.Messages({
"EmbeddedFileExtractorIngestModule.ArchiveExtractor.moduleName=Embedded File Extractor",
@ -65,4 +65,5 @@ public class EmbeddedFileExtractorModuleFactory extends IngestModuleFactoryAdapt
public FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings ingestOptions) {
return new EmbeddedFileExtractorIngestModule();
}
}

View File

@ -1,6 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<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>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
@ -16,12 +21,12 @@
<Layout>
<DimensionLayout dim="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>
</DimensionLayout>
<DimensionLayout dim="1">
<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>
</DimensionLayout>
</Layout>
@ -29,7 +34,7 @@
<Container class="javax.swing.JPanel" name="jPanel1">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[687, 450]"/>
<Dimension value="[718, 430]"/>
</Property>
</Properties>
@ -37,36 +42,45 @@
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="797" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="jScrollPane1" max="32767" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" 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>
</DimensionLayout>
</Layout>
<SubComponents>
<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"/>
<SubComponents>
<Container class="javax.swing.JSplitPane" name="jSplitPane1">
<Properties>
<Property name="dividerLocation" type="int" value="430"/>
<Property name="dividerLocation" type="int" value="365"/>
<Property name="dividerSize" type="int" value="1"/>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
<SubComponents>
<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>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="left"/>
@ -76,23 +90,26 @@
<Layout>
<DimensionLayout dim="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"/>
<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="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">
<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"/>
</Group>
</Group>
<EmptySpace min="0" pref="191" max="32767" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -101,14 +118,14 @@
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane2" pref="427" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jScrollPane2" pref="348" max="32767" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" 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"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -142,6 +159,15 @@
<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;)"/>
</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>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newTypeButtonActionPerformed"/>
@ -166,6 +192,11 @@
</SubComponents>
</Container>
<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>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="right"/>
@ -198,16 +229,16 @@
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="extHeaderLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane3" pref="427" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jScrollPane3" pref="348" max="32767" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="newExtButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="removeExtButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -221,6 +252,12 @@
<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;)"/>
</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>
<Events>
<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();
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);
mimePanel.setPreferredSize(new java.awt.Dimension(369, 424));
mimePanel.setRequestFocusEnabled(false);
jLabel1.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.jLabel1.text")); // NOI18N
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.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() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
newTypeButtonActionPerformed(evt);
@ -188,16 +198,18 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
.addGroup(mimePanelLayout.createSequentialGroup()
.addContainerGap()
.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.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel1)
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 349, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(mimePanelLayout.createSequentialGroup()
.addComponent(newTypeButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(newTypeButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(10, 10, 10)
.addComponent(removeTypeButton)))
.addGap(0, 191, Short.MAX_VALUE)))
.addContainerGap())
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
);
mimePanelLayout.setVerticalGroup(
mimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -205,18 +217,22 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
.addContainerGap()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 427, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 348, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.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))
.addContainerGap())
);
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.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() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
newExtButtonActionPerformed(evt);
@ -248,7 +264,7 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
.addGroup(extensionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(extHeaderLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 324, javax.swing.GroupLayout.PREFERRED_SIZE)
.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)
.addComponent(removeExtButton)))
.addGap(0, 0, Short.MAX_VALUE)))
@ -260,10 +276,10 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
.addContainerGap()
.addComponent(extHeaderLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 427, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 348, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.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))
.addContainerGap())
);
@ -277,27 +293,27 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 797, Short.MAX_VALUE)
.addContainerGap())
.addGap(0, 0, 0)
.addComponent(jScrollPane1)
.addGap(0, 0, 0))
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 504, Short.MAX_VALUE)
.addContainerGap())
.addGap(0, 0, 0)
.addComponent(jScrollPane1)
.addGap(0, 0, 0))
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 817, Short.MAX_VALUE)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 526, Short.MAX_VALUE)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents

View File

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

View File

@ -31,8 +31,8 @@ import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import org.openide.util.NbBundle;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
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 {
HashDatabase hashDb;
HashDb hashDb;
Pattern md5Pattern = Pattern.compile("^[a-fA-F0-9]{32}$");
List<HashEntry> hashes = 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
* database.
*/
AddHashValuesToDatabaseDialog(HashDatabase hashDb) {
AddHashValuesToDatabaseDialog(HashDb hashDb) {
super((JFrame) WindowManager.getDefault().getMainWindow(),
NbBundle.getMessage(AddHashValuesToDatabaseDialog.class, "AddHashValuesToDatabaseDialog.JDialog.Title", hashDb.getDisplayName()),
true);

View File

@ -31,9 +31,9 @@ import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.datamodel.HashEntry;
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 boolean disposeParent = false;
private final HashDatabase hashDb;
private final HashDb hashDb;
private final List<HashEntry> hashes;
private final List<String> invalidHashes;
private final Pattern md5Pattern;
@ -58,7 +58,7 @@ public class AddHashValuesToDatabaseProgressDialog extends javax.swing.JDialog {
* @param hashDb
* @param text
*/
AddHashValuesToDatabaseProgressDialog(AddHashValuesToDatabaseDialog parent, HashDatabase hashDb, String text) {
AddHashValuesToDatabaseProgressDialog(AddHashValuesToDatabaseDialog parent, HashDb hashDb, String text) {
super(parent);
initComponents();
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.EamDbException;
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.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
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.HashDbManagerException;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.TskCoreException;
@ -54,7 +55,7 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog {
private static final String DEFAULT_FILE_NAME = NbBundle
.getMessage(HashDbCreateDatabaseDialog.class, "HashDbCreateDatabaseDialog.defaultFileName");
private JFileChooser fileChooser = null;
private HashDatabase newHashDb = null;
private HashDb newHashDb = null;
private final static String LAST_FILE_PATH_KEY = "HashDbCreate_Path";
private EamOrganization selectedOrg = null;
private List<EamOrganization> orgs = null;
@ -77,7 +78,7 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog {
*
* @return A HashDb object or null.
*/
HashDatabase getHashDatabase() {
HashDb getHashDatabase() {
return newHashDb;
}
@ -474,9 +475,10 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog {
String errorMessage = NbBundle
.getMessage(this.getClass(), "HashDbCreateDatabaseDialog.errMsg.hashDbCreationErr");
if(fileTypeRadioButton.isSelected()){
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) {
Logger.getLogger(HashDbCreateDatabaseDialog.class.getName()).log(Level.WARNING, errorMessage, ex);
JOptionPane.showMessageDialog(this,
@ -519,10 +521,10 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog {
}
try{
int crIndex = EamDb.getInstance().newReferenceSet(selectedOrg.getOrgID(), hashSetNameTextField.getText(),
EamDb.getDefaultVersion(), fileKnown, false);
int referenceSetID = EamDb.getInstance().newReferenceSet(new EamGlobalSet(selectedOrg.getOrgID(), hashSetNameTextField.getText(),
EamDb.getDefaultVersion(), fileKnown, false));
newHashDb = HashDbManager.getInstance().addExistingCentralRepoHashSet(hashSetNameTextField.getText(),
EamDb.getDefaultVersion(), crIndex,
EamDb.getDefaultVersion(), referenceSetID,
true, sendIngestMessagesCheckbox.isSelected(), type, false);
} catch (EamDbException | TskCoreException 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.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType;
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
@ -52,7 +52,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog {
private JFileChooser fileChooser = new JFileChooser();
private String selectedFilePath = "";
private HashDatabase selectedHashDb = null;
private HashDb selectedHashDb = null;
private final static String LAST_FILE_PATH_KEY = "HashDbImport_Path";
private EamOrganization selectedOrg = null;
private List<EamOrganization> orgs = null;
@ -77,7 +77,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog {
*
* @return A HashDb object or null.
*/
HashDatabase getHashDatabase() {
HashDb getHashDatabase() {
return selectedHashDb;
}
@ -518,7 +518,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog {
if(fileTypeRadioButton.isSelected()){
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) {
Logger.getLogger(HashDbImportDatabaseDialog.class.getName()).log(Level.WARNING, errorMessage, ex);
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.IngestServices;
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.BlackboardArtifact;
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 HashDbManager hashDbManager = HashDbManager.getInstance();
private final HashLookupModuleSettings settings;
private List<HashDatabase> knownBadHashSets = new ArrayList<>();
private List<HashDatabase> knownHashSets = new ArrayList<>();
private List<HashDb> knownBadHashSets = new ArrayList<>();
private List<HashDb> knownHashSets = new ArrayList<>();
private long jobId;
private static final HashMap<Long, IngestJobTotals> totalsForIngestJobs = new HashMap<>();
private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter();
@ -96,8 +96,8 @@ public class HashDbIngestModule implements FileIngestModule {
if (!hashDbManager.verifyAllDatabasesLoadedCorrectly()) {
throw new IngestModuleException("Could not load all hash databases");
}
updateEnabledHashSets(hashDbManager.getNotableFileHashDatabases(), knownBadHashSets);
updateEnabledHashSets(hashDbManager.getKnownFileHashDatabases(), knownHashSets);
updateEnabledHashSets(hashDbManager.getKnownBadFileHashSets(), knownBadHashSets);
updateEnabledHashSets(hashDbManager.getKnownFileHashSets(), knownHashSets);
if (refCounter.incrementAndGet(jobId) == 1) {
// initialize job totals
@ -126,9 +126,9 @@ public class HashDbIngestModule implements FileIngestModule {
* @param allHashSets List of all hashsets from DB manager
* @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();
for (HashDatabase db : allHashSets) {
for (HashDb db : allHashSets) {
if (settings.isHashSetEnabled(db)) {
try {
if (db.isValid()) {
@ -196,7 +196,7 @@ public class HashDbIngestModule implements FileIngestModule {
// look up in notable first
boolean foundBad = false;
ProcessResult ret = ProcessResult.OK;
for (HashDatabase db : knownBadHashSets) {
for (HashDb db : knownBadHashSets) {
try {
long lookupstart = System.currentTimeMillis();
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
// a hit artifact or send a message to the application inbox.
if (!foundBad) {
for (HashDatabase db : knownHashSets) {
for (HashDb db : knownHashSets) {
try {
long lookupstart = System.currentTimeMillis();
if (db.lookupMD5Quick(file)) {
@ -359,7 +359,7 @@ public class HashDbIngestModule implements FileIngestModule {
}
private static synchronized void postSummary(long jobId,
List<HashDatabase> knownBadHashSets, List<HashDatabase> knownHashSets) {
List<HashDb> knownBadHashSets, List<HashDb> knownHashSets) {
IngestJobTotals jobTotals = getTotalsForIngestJobs(jobId);
totalsForIngestJobs.remove(jobId);
@ -384,8 +384,8 @@ public class HashDbIngestModule implements FileIngestModule {
detailsSb.append("<p>") //NON-NLS
.append(NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.complete.databasesUsed"))
.append("</p>\n<ul>"); //NON-NLS
for (HashDatabase db : knownBadHashSets) {
detailsSb.append("<li>").append(db.getDisplayName()).append("</li>\n"); //NON-NLS
for (HashDb db : knownBadHashSets) {
detailsSb.append("<li>").append(db.getHashSetName()).append("</li>\n"); //NON-NLS
}
detailsSb.append("</ul>"); //NON-NLS

View File

@ -65,7 +65,7 @@ public class HashDbManager implements PropertyChangeListener {
private static final String HASH_DATABASE_FILE_EXTENSON = "kdb"; //NON-NLS
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> hashSetPaths = new HashSet<>();
PropertyChangeSupport changeSupport = new PropertyChangeSupport(HashDbManager.class);
@ -153,7 +153,6 @@ public class HashDbManager implements PropertyChangeListener {
*
* @throws HashDbManagerException
*/
@Deprecated
public synchronized HashDb addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
HashDb hashDb = null;
hashDb = this.addExistingHashDatabaseNoSave(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType);
@ -161,12 +160,7 @@ public class HashDbManager implements PropertyChangeListener {
return hashDb;
}
@Deprecated
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;
try {
if (!new File(path).exists()) {
@ -181,7 +175,7 @@ public class HashDbManager implements PropertyChangeListener {
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) {
throw new HashDbManagerException(ex.getMessage());
}
@ -206,7 +200,6 @@ public class HashDbManager implements PropertyChangeListener {
*
* @throws HashDbManagerException
*/
@Deprecated
public synchronized HashDb addNewHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages,
HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
@ -218,14 +211,8 @@ public class HashDbManager implements PropertyChangeListener {
return hashDb;
}
@Deprecated
public synchronized HashDb addNewHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages,
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;
try {
File file = new File(path);
@ -245,16 +232,16 @@ public class HashDbManager implements PropertyChangeListener {
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) {
throw new HashDbManagerException(ex.getMessage());
}
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.
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
// accessor methods may throw.
@ -287,7 +274,7 @@ public class HashDbManager implements PropertyChangeListener {
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 readOnly) throws TskCoreException{
@ -295,7 +282,7 @@ public class HashDbManager implements PropertyChangeListener {
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);
if(! db.isValid()){
@ -319,7 +306,7 @@ public class HashDbManager implements PropertyChangeListener {
}
synchronized void indexHashDatabase(HashDb hashDb) {
synchronized void indexHashDatabase(SleuthkitHashSet hashDb) {
hashDb.addPropertyChangeListener(this);
HashDbIndexer creator = new HashDbIndexer(hashDb);
creator.execute();
@ -327,8 +314,8 @@ public class HashDbManager implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent event) {
if (event.getPropertyName().equals(HashDb.Event.INDEXING_DONE.name())) {
HashDb hashDb = (HashDb) event.getNewValue();
if (event.getPropertyName().equals(SleuthkitHashSet.Event.INDEXING_DONE.name())) {
SleuthkitHashSet hashDb = (SleuthkitHashSet) event.getNewValue();
if (null != hashDb) {
try {
String indexPath = hashDb.getIndexPath();
@ -350,12 +337,12 @@ public class HashDbManager implements PropertyChangeListener {
*
* @throws HashDbManagerException
*/
public synchronized void removeHashDatabase(HashDatabase hashDb) throws HashDbManagerException {
public synchronized void removeHashDatabase(HashDb hashDb) throws HashDbManagerException {
this.removeHashDatabaseNoSave(hashDb);
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
boolean ingestIsRunning = IngestManager.getInstance().isIngestRunning();
if (ingestIsRunning) {
@ -365,36 +352,36 @@ public class HashDbManager implements PropertyChangeListener {
// 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
// a mostly effective removal, even if the subsequent operations fail.
String hashSetName = hashDatabase.getHashSetName();
String hashSetName = hashDb.getHashSetName();
hashSetNames.remove(hashSetName);
hashSets.remove(hashDatabase);
hashSets.remove(hashDb);
// Now undertake the operations that could throw.
// Indexing is only relevanet for file type hashsets
if(hashDatabase instanceof HashDb){
HashDb hashDb = (HashDb)hashDatabase;
// Indexing is only relevanet for sleuthkit hashsets
if(hashDb instanceof SleuthkitHashSet){
SleuthkitHashSet hashDatabase = (SleuthkitHashSet)hashDb;
try {
if(hashDb.hasIndex()){
hashSetPaths.remove(hashDb.getIndexPath());
if(hashDatabase.hasIndex()){
hashSetPaths.remove(hashDatabase.getIndexPath());
}
} 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 {
if (!hashDb.hasIndexOnly()) {
hashSetPaths.remove(hashDb.getDatabasePath());
if (!hashDatabase.hasIndexOnly()) {
hashSetPaths.remove(hashDatabase.getDatabasePath());
}
} 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 {
hashDatabase.close();
} catch (TskCoreException ex) {
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error closing " + hashDatabase.getHashSetName() + " hash database when removing the database", ex); //NON-NLS
try {
hashDatabase.close();
} catch (TskCoreException ex) {
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
@ -418,56 +405,24 @@ public class HashDbManager implements PropertyChangeListener {
throw new HashDbManagerException(NbBundle.getMessage(this.getClass(), "HashDbManager.saveErrorExceptionMsg"));
}
}
/**
* 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.
*/
@Deprecated
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{
updateHashSetsFromCentralRepository();
} catch (TskCoreException ex){
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS
}
return getAllHashDatabases();
List<HashDb> hashDbs = new ArrayList<>();
hashDbs.addAll(this.hashSets);
return hashDbs;
}
/**
@ -475,49 +430,31 @@ public class HashDbManager implements PropertyChangeListener {
*
* @return A list, possibly empty, of hash databases.
*/
@Deprecated
public synchronized List<HashDb> getKnownFileHashSets() {
List<HashDb> hashDbs = new ArrayList<>();
this.hashSets.stream().filter((thisSet) -> ((thisSet instanceof HashDb) && (thisSet.getKnownFilesType() == HashDb.KnownFilesType.KNOWN))).forEach((thisSet) -> {
hashDbs.add((HashDb)thisSet);
});
return hashDbs;
}
/**
* Gets all of the hash databases used to classify files as known.
*
* @return A list, possibly empty, of hash databases.
*/
public synchronized List<HashDatabase> getKnownFileHashDatabases() {
List<HashDatabase> 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) -> {
hashDbs.add(db);
});
return hashDbs;
}
}
/**
* Gets all of the hash databases used to classify files as notable.
*
* @return A list, possibly empty, of hash databases.
*/
@Deprecated
public synchronized List<HashDb> getKnownBadFileHashSets() {
List<HashDb> hashDbs = new ArrayList<>();
this.hashSets.stream().filter((thisSet) -> ((thisSet instanceof HashDb) && (thisSet.getKnownFilesType() == HashDb.KnownFilesType.KNOWN_BAD))).forEach((thisSet) -> {
hashDbs.add((HashDb)thisSet);
});
return hashDbs;
}
/**
* 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<>();
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_BAD)).forEach((db) -> {
hashDbs.add(db);
});
@ -529,28 +466,18 @@ public class HashDbManager implements PropertyChangeListener {
*
* @return A list, possibly empty, of hash databases.
*/
@Deprecated
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);
}
private List<HashDatabase> getUpdateableHashSets(List<HashDatabase> hashDbs) {
ArrayList<HashDatabase> updateableDbs = new ArrayList<>();
for (HashDatabase db : hashDbs) {
private List<HashDb> getUpdateableHashSets(List<HashDb> hashDbs) {
ArrayList<HashDb> updateableDbs = new ArrayList<>();
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 {
if (db.isUpdateable()) {
updateableDbs.add(db);
@ -572,9 +499,9 @@ public class HashDbManager implements PropertyChangeListener {
// Defaults for fields not stored in the central repository:
// searchDuringIngest: false
// 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(),
globalSet.getGlobalSetID(), globalSet.getKnownStatus(), globalSet.isReadOnly(), false, sendIngestMessages));
globalSet.getGlobalSetID(), convertFileKnown(globalSet.getFileKnownStatus()), globalSet.isReadOnly(), false, sendIngestMessages));
}
} catch (EamDbException ex){
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS
@ -582,6 +509,13 @@ public class HashDbManager implements PropertyChangeListener {
}
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
@ -595,12 +529,14 @@ public class HashDbManager implements PropertyChangeListener {
loadHashsetsConfiguration();
}
private void closeHashDatabases(List<HashDatabase> hashDatabases) {
for (HashDatabase database : hashDatabases) {
try {
database.close();
} catch (TskCoreException ex) {
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error closing " + database.getHashSetName() + " hash database", ex); //NON-NLS
private void closeHashDatabases(List<HashDb> hashDatabases) {
for (HashDb database : hashDatabases) {
if(database instanceof SleuthkitHashSet){
try {
((SleuthkitHashSet)database).close();
} catch (TskCoreException ex) {
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error closing " + database.getHashSetName() + " hash database", ex); //NON-NLS
}
}
}
hashDatabases.clear();
@ -631,7 +567,7 @@ public class HashDbManager implements PropertyChangeListener {
if(hashDbInfo.isFileDatabaseType()){
String dbPath = this.getValidFilePath(hashDbInfo.getHashSetName(), hashDbInfo.getPath());
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 {
logger.log(Level.WARNING, Bundle.HashDbManager_noDbPath_message(hashDbInfo.getHashSetName()));
allDatabasesLoadedCorrectly = false;
@ -687,7 +623,7 @@ public class HashDbManager implements PropertyChangeListener {
}
}
void updateHashSetsFromCentralRepository() throws TskCoreException {
private void updateHashSetsFromCentralRepository() throws TskCoreException {
if(EamDb.isEnabled()){
List<HashDbInfo> crHashDbInfoList = getCentralRepoHashSetsFromDatabase();
for(HashDbInfo hashDbInfo : crHashDbInfoList) {
@ -702,7 +638,7 @@ public class HashDbManager implements PropertyChangeListener {
}
private boolean hashDbInfoIsNew(HashDbInfo dbInfo){
for(HashDatabase db:this.hashSets){
for(HashDb db:this.hashSets){
if(dbInfo.matches(db)){
return false;
}
@ -757,87 +693,8 @@ public class HashDbManager implements PropertyChangeListener {
return filePath;
}
public static interface HashDatabase {
enum DatabaseType{
FILE,
CENTRAL_REPOSITORY
};
public static abstract class HashDb {
public String getHashSetName();
public String getDisplayName();
public String getDatabasePath() throws TskCoreException;
public HashDb.KnownFilesType getKnownFilesType();
public boolean getSearchDuringIngest();
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
* object should be classified.
@ -864,6 +721,79 @@ public class HashDbManager implements PropertyChangeListener {
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 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 final int handle;
private final String hashSetName;
@ -873,7 +803,7 @@ public class HashDbManager implements PropertyChangeListener {
private boolean indexing;
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.hashSetName = hashSetName;
this.searchDuringIngest = useForIngest;
@ -903,8 +833,7 @@ public class HashDbManager implements PropertyChangeListener {
propertyChangeSupport.removePropertyChangeListener(pcl);
}
@Override
public int getHandle(){
int getHandle(){
return handle;
}
@ -914,7 +843,7 @@ public class HashDbManager implements PropertyChangeListener {
}
@Override
public String getDisplayName(){
String getDisplayName(){
return getHashSetName();
}
@ -926,12 +855,8 @@ public class HashDbManager implements PropertyChangeListener {
public void setIndexing(boolean indexing){
this.indexing = indexing;
}
@Override
public DatabaseType getDatabaseType(){
return DatabaseType.FILE;
}
@Override
public String getIndexPath() throws TskCoreException {
return SleuthkitJNI.getHashDatabaseIndexPath(handle);
}
@ -947,7 +872,7 @@ public class HashDbManager implements PropertyChangeListener {
}
@Override
public void setSearchDuringIngest(boolean useForIngest) {
void setSearchDuringIngest(boolean useForIngest) {
this.searchDuringIngest = useForIngest;
}
@ -957,7 +882,7 @@ public class HashDbManager implements PropertyChangeListener {
}
@Override
public void setSendIngestMessages(boolean showInboxMessages) {
void setSendIngestMessages(boolean showInboxMessages) {
this.sendIngestMessages = showInboxMessages;
}
@ -1072,23 +997,24 @@ public class HashDbManager implements PropertyChangeListener {
* @throws TskCoreException
*/
@Override
public boolean isValid() throws TskCoreException {
boolean isValid() throws TskCoreException {
return hasIndex();
}
public boolean hasIndex() throws TskCoreException {
boolean hasIndex() throws TskCoreException {
return SleuthkitJNI.hashDatabaseHasLookupIndex(handle);
}
@Override
public boolean hasIndexOnly() throws TskCoreException {
return SleuthkitJNI.hashDatabaseIsIndexOnly(handle);
}
public boolean canBeReIndexed() throws TskCoreException {
boolean canBeReIndexed() throws TskCoreException {
return SleuthkitJNI.hashDatabaseCanBeReindexed(handle);
}
public boolean isIndexing() {
boolean isIndexing() {
return indexing;
}
@ -1097,8 +1023,7 @@ public class HashDbManager implements PropertyChangeListener {
this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
}
@Override
public void close() throws TskCoreException {
private void close() throws TskCoreException {
SleuthkitJNI.closeHashDatabase(handle);
}
@ -1126,7 +1051,7 @@ public class HashDbManager implements PropertyChangeListener {
if (getClass() != obj.getClass()) {
return false;
}
final HashDb other = (HashDb) obj;
final SleuthkitHashSet other = (SleuthkitHashSet) obj;
if (!Objects.equals(this.hashSetName, other.hashSetName)) {
return false;
}
@ -1141,7 +1066,7 @@ public class HashDbManager implements PropertyChangeListener {
* Instances of this class represent hash databases used to classify files
* as known or know bad.
*/
public static class CentralRepoHashDb implements HashDatabase{
class CentralRepoHashSet extends HashDb{
private static final long serialVersionUID = 1L;
private final String hashSetName;
@ -1155,7 +1080,7 @@ public class HashDbManager implements PropertyChangeListener {
private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
@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 readOnly)
throws TskCoreException{
@ -1170,7 +1095,7 @@ public class HashDbManager implements PropertyChangeListener {
try{
orgName = EamDb.getInstance().getReferenceSetOrganization(referenceSetID).getName();
} 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();
}
}
@ -1197,8 +1122,8 @@ public class HashDbManager implements PropertyChangeListener {
}
@Override
public int getHandle(){
return 0;
public boolean hasIndexOnly() throws TskCoreException{
return true;
}
@Override
@ -1215,15 +1140,15 @@ public class HashDbManager implements PropertyChangeListener {
}
}
public String getVersion(){
String getVersion(){
return version;
}
public String getOrgName(){
String getOrgName(){
return orgName;
}
public int getReferenceSetID(){
int getReferenceSetID(){
return referenceSetID;
}
@ -1231,12 +1156,8 @@ public class HashDbManager implements PropertyChangeListener {
public String getDatabasePath() throws TskCoreException {
return "";
}
@Override
public DatabaseType getDatabaseType(){
return DatabaseType.CENTRAL_REPOSITORY;
}
@Override
public String getIndexPath() throws TskCoreException {
return "";
}
@ -1252,7 +1173,7 @@ public class HashDbManager implements PropertyChangeListener {
}
@Override
public void setSearchDuringIngest(boolean useForIngest) {
void setSearchDuringIngest(boolean useForIngest) {
this.searchDuringIngest = useForIngest;
}
@ -1262,7 +1183,7 @@ public class HashDbManager implements PropertyChangeListener {
}
@Override
public void setSendIngestMessages(boolean showInboxMessages) {
void setSendIngestMessages(boolean showInboxMessages) {
this.sendIngestMessages = showInboxMessages;
}
@ -1349,7 +1270,7 @@ public class HashDbManager implements PropertyChangeListener {
EamDb.getInstance().bulkInsertReferenceTypeEntries(globalFileInstances,
EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID));
} catch (EamDbException ex){
throw new TskCoreException("Error adding hashes", ex);
throw new TskCoreException("Error adding hashes to " + getDisplayName(), ex);
}
}
@ -1370,9 +1291,10 @@ public class HashDbManager implements PropertyChangeListener {
AbstractFile file = (AbstractFile) content;
if (null != file.getMd5Hash()) {
try{
return EamDb.getInstance().isHashInReferenceSet(file.getMd5Hash(), this.referenceSetID);
return EamDb.getInstance().isFileHashInReferenceSet(file.getMd5Hash(), this.referenceSetID);
} 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);
}
}
@ -1398,12 +1320,13 @@ public class HashDbManager implements PropertyChangeListener {
AbstractFile file = (AbstractFile) content;
if (null != file.getMd5Hash()) {
try{
if(EamDb.getInstance().isHashInReferenceSet(file.getMd5Hash(), this.referenceSetID)){
if(EamDb.getInstance().isFileHashInReferenceSet(file.getMd5Hash(), this.referenceSetID)){
// Make a bare-bones HashHitInfo for now
result = new HashHitInfo(file.getMd5Hash(), "", "");
}
} 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);
}
}
@ -1415,17 +1338,16 @@ public class HashDbManager implements PropertyChangeListener {
* Returns whether this database can be enabled.
*
* @return true if is valid, false otherwise
* @throws TskCoreException
*/
@Override
public boolean isValid() {
boolean isValid() {
if(! EamDb.isEnabled()) {
return false;
}
try{
return EamDb.getInstance().referenceSetIsValid(this.referenceSetID, this.hashSetName, this.version);
} 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;
}
}
@ -1434,11 +1356,6 @@ public class HashDbManager implements PropertyChangeListener {
public void firePropertyChange(String propertyName, Object oldValue, Object newValue){
this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
}
@Override
public void close() throws TskCoreException {
}
@Override
public String toString(){
@ -1464,7 +1381,7 @@ public class HashDbManager implements PropertyChangeListener {
if (getClass() != obj.getClass()) {
return false;
}
final CentralRepoHashDb other = (CentralRepoHashDb) obj;
final CentralRepoHashSet other = (CentralRepoHashSet) obj;
if (!Objects.equals(this.hashSetName, other.hashSetName)) {
return false;
}
@ -1484,9 +1401,9 @@ public class HashDbManager implements PropertyChangeListener {
private class HashDbIndexer extends SwingWorker<Object, Void> {
private ProgressHandle progress = null;
private HashDb hashDb = null;
private SleuthkitHashSet hashDb = null;
HashDbIndexer(HashDb hashDb) {
HashDbIndexer(SleuthkitHashSet hashDb) {
this.hashDb = hashDb;
}
@ -1500,7 +1417,7 @@ public class HashDbManager implements PropertyChangeListener {
try {
SleuthkitJNI.createLookupIndexForHashDatabase(hashDb.getHandle());
} 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,
NbBundle.getMessage(this.getClass(),
"HashDbManager.dlgMsg.errorIndexingHashSet",
@ -1530,7 +1447,7 @@ public class HashDbManager implements PropertyChangeListener {
}
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());
} catch (Exception e) {
logger.log(Level.SEVERE, "HashDbManager listener threw exception", e); //NON-NLS

View File

@ -60,7 +60,7 @@ public class HashLookupModuleFactory extends IngestModuleFactoryAdapter {
@Override
public IngestModuleIngestJobSettings getDefaultIngestJobSettings() {
// 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

View File

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

View File

@ -30,8 +30,8 @@ import javax.swing.table.TableColumn;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase;
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) {
try{
hashDbManager.updateHashSetsFromCentralRepository();
} 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);
initializeHashSetModels(settings, validSetsOnly(hashDbManager.getKnownFileHashSets()), knownHashSetModels);
initializeHashSetModels(settings, validSetsOnly(hashDbManager.getKnownBadFileHashSets()), 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();
for (HashDatabase db : hashDbs) {
for (HashDb db : hashDbs) {
hashSetModels.add(new HashSetModel(db, settings.isHashSetEnabled(db), isHashDbValid(db)));
}
}
@ -105,15 +100,15 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe
@Override
public IngestModuleIngestJobSettings getSettings() {
List<HashDatabase> enabledHashSets = new ArrayList<>();
List<HashDatabase> disabledHashSets = new ArrayList<>();
List<HashDb> enabledHashSets = new ArrayList<>();
List<HashDb> disabledHashSets = new ArrayList<>();
addHashSets(knownHashSetModels, enabledHashSets, disabledHashSets);
addHashSets(knownBadHashSetModels, enabledHashSets, disabledHashSets);
return new HashLookupModuleSettings(alwaysCalcHashesCheckbox.isSelected(),
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) {
if (model.isEnabled() && model.isValid()) {
enabledHashSets.add(model.getDatabase());
@ -130,19 +125,33 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe
}
private void updateHashSetModels() {
updateHashSetModels(hashDbManager.getKnownFileHashDatabases(), knownHashSetModels);
updateHashSetModels(hashDbManager.getNotableFileHashDatabases(), knownBadHashSetModels);
updateHashSetModels(validSetsOnly(hashDbManager.getKnownFileHashSets()), knownHashSetModels);
updateHashSetModels(validSetsOnly(hashDbManager.getKnownBadFileHashSets()), knownBadHashSetModels);
}
private List<HashDb> validSetsOnly(List<HashDb> hashDbs){
List<HashDb> validDbs = new ArrayList<>();
for(HashDb db:hashDbs){
try{
if(db.isValid()){
validDbs.add(db);
}
} catch (TskCoreException ex){
Logger.getLogger(HashLookupModuleSettingsPanel.class.getName()).log(Level.SEVERE, "Error checking validity for hash set (name = " + db.getHashSetName() + ")", ex); //NON-NLS
}
}
return validDbs;
}
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.
List<HashSetModel> deletedHashSetModels = new ArrayList<>();
for (HashSetModel model : hashSetModels) {
boolean foundDatabase = false;
for(HashDatabase db : hashDatabases){
for(HashDb db : hashDatabases){
if(model.getDatabase().equals(db)){
model.setValid(isHashDbValid(db));
hashDatabases.remove(db);
@ -161,7 +170,7 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe
}
// 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)));
}
}
@ -173,7 +182,7 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe
knownBadHashSetsTableModel.fireTableDataChanged();
}
private boolean isHashDbValid(HashDatabase hashDb) {
private boolean isHashDbValid(HashDb hashDb) {
boolean isValid = false;
try {
isValid = hashDb.isValid();
@ -185,17 +194,17 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe
private static final class HashSetModel {
private final HashDatabase db;
private final HashDb db;
private boolean valid;
private boolean enabled;
HashSetModel(HashDatabase db, boolean enabled, boolean valid) {
HashSetModel(HashDb db, boolean enabled, boolean valid) {
this.db = db;
this.enabled = enabled;
this.valid = valid;
}
HashDatabase getDatabase(){
HashDb getDatabase(){
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.PlatformUtil;
import org.sleuthkit.autopsy.coreutils.XMLUtil;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase.DatabaseType;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.CentralRepoHashDb;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.CentralRepoHashSet;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.SleuthkitHashSet;
import org.sleuthkit.datamodel.TskCoreException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
/**
* Class to represent the settings to be serialized for hash lookup.
@ -74,9 +74,9 @@ final class HashLookupSettings implements Serializable {
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<>();
for(HashDbManager.HashDatabase db:hashSets){
for(HashDbManager.HashDb db:hashSets){
try{
dbInfoList.add(new HashDbInfo(db));
} catch (TskCoreException ex){
@ -297,6 +297,11 @@ final class HashLookupSettings implements Serializable {
*/
static final class HashDbInfo implements Serializable {
enum DatabaseType{
FILE,
CENTRAL_REPOSITORY
};
private static final long serialVersionUID = 1L;
private final String hashSetName;
private final HashDbManager.HashDb.KnownFilesType knownFilesType;
@ -342,9 +347,9 @@ final class HashLookupSettings implements Serializable {
dbType = DatabaseType.CENTRAL_REPOSITORY;
}
HashDbInfo(HashDbManager.HashDatabase db) throws TskCoreException{
if(db instanceof HashDbManager.HashDb){
HashDbManager.HashDb fileTypeDb = (HashDbManager.HashDb)db;
HashDbInfo(HashDbManager.HashDb db) throws TskCoreException{
if(db instanceof HashDbManager.SleuthkitHashSet){
HashDbManager.SleuthkitHashSet fileTypeDb = (HashDbManager.SleuthkitHashSet)db;
this.hashSetName = fileTypeDb.getHashSetName();
this.knownFilesType = fileTypeDb.getKnownFilesType();
this.searchDuringIngest = fileTypeDb.getSearchDuringIngest();
@ -359,7 +364,7 @@ final class HashLookupSettings implements Serializable {
this.path = fileTypeDb.getDatabasePath();
}
} else {
HashDbManager.CentralRepoHashDb centralRepoDb = (HashDbManager.CentralRepoHashDb)db;
HashDbManager.CentralRepoHashSet centralRepoDb = (HashDbManager.CentralRepoHashSet)db;
this.hashSetName = centralRepoDb.getHashSetName();
this.version = centralRepoDb.getVersion();
this.knownFilesType = centralRepoDb.getKnownFilesType();
@ -457,7 +462,7 @@ final class HashLookupSettings implements Serializable {
return dbType == DatabaseType.CENTRAL_REPOSITORY;
}
boolean matches(HashDatabase hashDb){
boolean matches(HashDb hashDb){
if(hashDb == null){
return false;
}
@ -466,7 +471,8 @@ final class HashLookupSettings implements Serializable {
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;
}
@ -474,19 +480,15 @@ final class HashLookupSettings implements Serializable {
return false;
}
if(this.dbType.equals(DatabaseType.FILE)){
// FILE types will always have unique names, so no more testing required
return true;
}
// Central repo tests
CentralRepoHashDb crDb = (CentralRepoHashDb) hashDb;
if(this.referenceSetID != crDb.getReferenceSetID()){
return false;
}
if(! version.equals(crDb.getVersion())){
return false;
if(hashDb instanceof CentralRepoHashSet){
CentralRepoHashSet crDb = (CentralRepoHashSet) hashDb;
if(this.referenceSetID != crDb.getReferenceSetID()){
return false;
}
if(! version.equals(crDb.getVersion())){
return false;
}
}
return true;

View File

@ -45,11 +45,11 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.events.AutopsyEvent;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.CentralRepoHashDb;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.SleuthkitHashSet;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.CentralRepoHashSet;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType;
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
@ -65,7 +65,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
.getMessage(HashLookupSettingsPanel.class, "HashDbConfigPanel.errorGettingIndexStatusText");
private final HashDbManager hashSetManager = HashDbManager.getInstance();
private final HashSetTableModel hashSetTableModel = new HashSetTableModel();
private final List<CentralRepoHashDb> newReferenceSets = new ArrayList<>();
private final List<Integer> newReferenceSetIDs = new ArrayList<>();
public HashLookupSettingsPanel() {
initComponents();
@ -108,7 +108,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
}
private void updateComponents() {
HashDatabase db = ((HashSetTable) hashSetTable).getSelection();
HashDb db = ((HashSetTable) hashSetTable).getSelection();
if (db != null) {
updateComponentsForSelection(db);
} else {
@ -157,7 +157,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
"HashLookupSettingsPanel.notApplicable=N/A",
"HashLookupSettingsPanel.centralRepo=Central Repository"
})
private void updateComponentsForSelection(HashDatabase db) {
private void updateComponentsForSelection(HashDb db) {
boolean ingestIsRunning = IngestManager.getInstance().isIngestRunning();
// Update descriptive labels.
@ -180,8 +180,8 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
addHashesToDatabaseButton.setEnabled(false);
}
if(db instanceof HashDb){
HashDb hashDb = (HashDb)db;
if(db instanceof SleuthkitHashSet){
SleuthkitHashSet hashDb = (SleuthkitHashSet)db;
// Disable the central repo fields
hashDbVersionLabel.setText(Bundle.HashLookupSettingsPanel_notApplicable());
@ -253,7 +253,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
indexButton.setEnabled(false);
deleteDatabaseButton.setEnabled(false);
CentralRepoHashDb crDb = (CentralRepoHashDb)db;
CentralRepoHashSet crDb = (CentralRepoHashSet)db;
hashDbVersionLabel.setText(crDb.getVersion());
hashDbOrgLabel.setText(crDb.getOrgName());
@ -302,15 +302,19 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
@Override
@Messages({"HashLookupSettingsPanel.saveFail.message=Couldn't save hash db settings.",
"HashLookupSettingsPanel.saveFail.title=Save Fail"})
public void saveSettings() {
public void saveSettings() {
// Clear out the list of new central repo hash sets. They don't need to be
// indexed so will all be saved on both code paths.
newReferenceSetIDs.clear();
//Checking for for any unindexed databases
List<HashDb> unindexed = new ArrayList<>();
for (HashDatabase hashSet : hashSetManager.getAllHashDatabases()) {
if(hashSet instanceof HashDb){
HashDb db = (HashDb)hashSet;
List<SleuthkitHashSet> unindexed = new ArrayList<>();
for (HashDb db : hashSetManager.getAllHashSets()) {
if(db instanceof SleuthkitHashSet){
try {
if (!db.hasIndex()) {
unindexed.add(db);
SleuthkitHashSet hashDatabase = (SleuthkitHashSet)db;
if (!hashDatabase.hasIndex()) {
unindexed.add(hashDatabase);
}
} catch (TskCoreException ex) {
Logger.getLogger(HashLookupSettingsPanel.class.getName()).log(Level.SEVERE, "Error getting index info for hash database", ex); //NON-NLS
@ -318,21 +322,28 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
}
}
//If unindexed ones are found, show a popup box that will either index them, or remove them.
if (unindexed.size() == 1) {
showInvalidIndex(false, unindexed);
} else if (unindexed.size() > 1) {
showInvalidIndex(true, unindexed);
}
try {
hashSetManager.save();
HashDbManager.getInstance().saveNewCentralRepoDatabases(newReferenceSets);
newReferenceSets.clear();
} catch (HashDbManager.HashDbManagerException ex) {
SwingUtilities.invokeLater(() -> {
JOptionPane.showMessageDialog(null, Bundle.HashLookupSettingsPanel_saveFail_message(), Bundle.HashLookupSettingsPanel_saveFail_title(), JOptionPane.ERROR_MESSAGE);
// If there are unindexed databases, give the user the option to index them now. This
// needs to be on the EDT, and will save the hash settings after completing
if(! unindexed.isEmpty()){
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run(){
//If unindexed ones are found, show a popup box that will either index them, or remove them.
if (unindexed.size() == 1) {
showInvalidIndex(false, unindexed);
} else if (unindexed.size() > 1) {
showInvalidIndex(true, unindexed);
}
}
});
} else {
try {
hashSetManager.save();
} catch (HashDbManager.HashDbManagerException ex) {
SwingUtilities.invokeLater(() -> {
JOptionPane.showMessageDialog(null, Bundle.HashLookupSettingsPanel_saveFail_message(), Bundle.HashLookupSettingsPanel_saveFail_title(), JOptionPane.ERROR_MESSAGE);
});
}
}
}
@ -355,10 +366,10 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
*/
if (IngestManager.getInstance().isIngestRunning() == false) {
// Remove any new central repo hash sets from the database
for(CentralRepoHashDb db:newReferenceSets){
for(Integer referenceSetID:newReferenceSetIDs){
try{
if(EamDb.isEnabled()){
EamDb.getInstance().deleteReferenceSet(db.getReferenceSetID());
EamDb.getInstance().deleteReferenceSet(referenceSetID);
} else {
// This is the case where the user imported a database, then switched over to the central
// repo panel and disabled it before cancelling. We can't delete the database at this point.
@ -368,15 +379,15 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
Logger.getLogger(HashLookupSettingsPanel.class.getName()).log(Level.SEVERE, "Error reverting central repository hash sets", ex); //NON-NLS
}
}
newReferenceSets.clear();
newReferenceSetIDs.clear();
HashDbManager.getInstance().loadLastSavedConfiguration();
}
}
@Messages({"# {0} - hash lookup name", "HashLookupSettingsPanel.removeDatabaseFailure.message=Failed to remove hash lookup: {0}"})
void removeThese(List<HashDb> toRemove) {
for (HashDb hashDb : toRemove) {
void removeThese(List<SleuthkitHashSet> toRemove) {
for (SleuthkitHashSet hashDb : toRemove) {
try {
hashSetManager.removeHashDatabaseNoSave(hashDb);
} catch (HashDbManager.HashDbManagerException ex) {
@ -394,10 +405,10 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
* @param plural Whether or not there are multiple unindexed databases
* @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 message;
for (HashDatabase hdb : unindexed) {
for (HashDb hdb : unindexed) {
total += "\n" + hdb.getHashSetName();
}
if (plural) {
@ -421,6 +432,11 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
"HashDbConfigPanel.allUnindexedDbsRmFromListMsg"));
removeThese(unindexed);
}
try {
hashSetManager.save();
} catch (HashDbManager.HashDbManagerException ex) {
JOptionPane.showMessageDialog(null, Bundle.HashLookupSettingsPanel_saveFail_message(), Bundle.HashLookupSettingsPanel_saveFail_title(), JOptionPane.ERROR_MESSAGE);
}
}
boolean valid() {
@ -450,7 +466,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
return cellRenderer;
}
public HashDatabase getSelection() {
public HashDb getSelection() {
return hashSetTableModel.getHashSetAt(getSelectionModel().getMinSelectionIndex());
}
@ -460,7 +476,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
}
}
public void selectRowByDatabase(HashDatabase db){
public void selectRowByDatabase(HashDb db){
setSelection(hashSetTableModel.getIndexByDatabase(db));
}
@ -476,7 +492,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
*/
private class HashSetTableModel extends AbstractTableModel {
List<HashDatabase> hashSets = HashDbManager.getInstance().getAllHashDatabases();
List<HashDb> hashSets = HashDbManager.getInstance().getAllHashSets();
@Override
public int getColumnCount() {
@ -523,7 +539,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
return getValueAt(0, c).getClass();
}
HashDatabase getHashSetAt(int index) {
HashDb getHashSetAt(int index) {
if (!hashSets.isEmpty() && index >= 0 && index < hashSets.size()) {
return hashSets.get(index);
} else {
@ -531,7 +547,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
}
}
int getIndexByDatabase(HashDatabase db){
int getIndexByDatabase(HashDb db){
for (int i = 0; i < hashSets.size(); ++i) {
if (hashSets.get(i).equals(db)) {
return i;
@ -551,7 +567,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
}
void refreshModel() {
hashSets = HashDbManager.getInstance().refreshAndGetAllHashDatabases();
hashSets = HashDbManager.getInstance().getAllHashSets();
refreshDisplay();
}
@ -915,16 +931,16 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
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);
}//GEN-LAST:event_addHashesToDatabaseButtonActionPerformed
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(hashDb instanceof CentralRepoHashDb){
CentralRepoHashDb crDb = (CentralRepoHashDb)hashDb;
newReferenceSets.add(crDb);
if(hashDb instanceof CentralRepoHashSet){
int newDbIndex = ((CentralRepoHashSet)hashDb).getReferenceSetID();
newReferenceSetIDs.add(newDbIndex);
}
hashSetTableModel.refreshModel();
@ -934,7 +950,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
}//GEN-LAST:event_createDatabaseButtonActionPerformed
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) {
hashDb.setSendIngestMessages(sendIngestMessagesCheckBox.isSelected());
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
@ -942,18 +958,18 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
}//GEN-LAST:event_sendIngestMessagesCheckBoxActionPerformed
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 instanceof HashDb;
assert hashDatabase instanceof SleuthkitHashSet;
// Add a listener for the INDEXING_DONE event. This listener will update
// the UI.
HashDb hashDb = (HashDb)hashDatabase;
SleuthkitHashSet hashDb = (SleuthkitHashSet)hashDatabase;
hashDb.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(HashDb.Event.INDEXING_DONE.toString())) {
HashDatabase selectedHashDb = ((HashSetTable) hashSetTable).getSelection();
if (evt.getPropertyName().equals(SleuthkitHashSet.Event.INDEXING_DONE.toString())) {
HashDb selectedHashDb = ((HashSetTable) hashSetTable).getSelection();
if (selectedHashDb != null && hashDb != null && hashDb.equals(selectedHashDb)) {
updateComponents();
}
@ -974,11 +990,11 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
}//GEN-LAST:event_indexButtonActionPerformed
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(hashDb instanceof CentralRepoHashDb){
CentralRepoHashDb crDb = (CentralRepoHashDb)hashDb;
newReferenceSets.add(crDb);
if(hashDb instanceof CentralRepoHashSet){
int newReferenceSetID = ((CentralRepoHashSet)hashDb).getReferenceSetID();
newReferenceSetIDs.add(newReferenceSetID);
}
hashSetTableModel.refreshModel();
@ -995,7 +1011,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
NbBundle.getMessage(this.getClass(), "HashDbConfigPanel.deleteDbActionMsg"),
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) {
HashDatabase hashDb = ((HashSetTable) hashSetTable).getSelection();
HashDb hashDb = ((HashSetTable) hashSetTable).getSelection();
if (hashDb != null) {
try {
hashSetManager.removeHashDatabaseNoSave(hashDb);
@ -1010,7 +1026,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
private void hashSetTableKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_hashSetTableKeyPressed
if (evt.getKeyCode() == KeyEvent.VK_DELETE) {
HashDatabase hashDb = ((HashSetTable) hashSetTable).getSelection();
HashDb hashDb = ((HashSetTable) hashSetTable).getSelection();
if (hashDb != null) {
try {
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.EamDbException;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamGlobalFileInstance;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamGlobalSet;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
@ -92,7 +93,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P
this.setVisible(true);
}
HashDbManager.HashDatabase getDatabase(){
HashDbManager.HashDb getDatabase(){
if(worker != null){
return worker.getDatabase();
}
@ -128,7 +129,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P
void addPropertyChangeListener(PropertyChangeListener dialog);
int getProgressPercentage();
long getLinesProcessed();
HashDbManager.HashDatabase getDatabase();
HashDbManager.HashDb getDatabase();
}
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 long totalLines;
private int referenceSetID = -1;
private HashDbManager.CentralRepoHashDb newHashDb = null;
private HashDbManager.CentralRepoHashSet newHashDb = null;
private final AtomicLong numLines = new AtomicLong();
ImportIDXWorker(String hashSetName, String version, int orgId,
@ -176,7 +177,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P
}
@Override
public HashDbManager.HashDatabase getDatabase(){
public HashDbManager.HashDb getDatabase(){
return newHashDb;
}
@ -201,7 +202,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P
}
// 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();
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 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
@ -43,8 +43,8 @@ import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
*/
class ModalNoButtons extends javax.swing.JDialog implements PropertyChangeListener {
List<HashDb> unindexed;
HashDb toIndex;
List<SleuthkitHashSet> unindexed;
SleuthkitHashSet toIndex;
HashLookupSettingsPanel hdbmp;
int length = 0;
int currentcount = 1;
@ -58,7 +58,7 @@ class ModalNoButtons extends javax.swing.JDialog implements PropertyChangeListen
* @param parent Swing parent frame.
* @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);
this.unindexed = unindexed;
this.toIndex = null;
@ -75,7 +75,7 @@ class ModalNoButtons extends javax.swing.JDialog implements PropertyChangeListen
* @param parent Swing parent frame.
* @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);
this.unindexed = null;
this.toIndex = unindexed;
@ -183,7 +183,7 @@ class ModalNoButtons extends javax.swing.JDialog implements PropertyChangeListen
"ModalNoButtons.dlgTitle.unfinishedIndexing"),
JOptionPane.YES_NO_OPTION);
if (res == JOptionPane.YES_OPTION) {
List<HashDb> remove = new ArrayList<>();
List<SleuthkitHashSet> remove = new ArrayList<>();
if (this.toIndex == null) {
remove = this.unindexed;
} else {
@ -230,7 +230,7 @@ class ModalNoButtons extends javax.swing.JDialog implements PropertyChangeListen
private void indexThese() {
length = this.unindexed.size();
this.INDEXING_PROGBAR.setIndeterminate(true);
for (HashDb db : this.unindexed) {
for (SleuthkitHashSet db : this.unindexed) {
currentDb = db.getHashSetName();
this.CURRENTDB_LABEL.setText("(" + currentDb + ")");
this.CURRENTLYON_LABEL.setText(
@ -255,7 +255,7 @@ class ModalNoButtons extends javax.swing.JDialog implements PropertyChangeListen
* this dialog if all indexing is complete.
*/
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) {
this.INDEXING_PROGBAR.setValue(100);
this.setModal(false);

View File

@ -27,6 +27,7 @@ import javax.swing.JPanel;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.casemodule.Case;
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.ReportProgressPanel;
import org.sleuthkit.datamodel.AbstractFile;
@ -34,7 +35,6 @@ import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ContentTag;
import org.sleuthkit.datamodel.TagName;
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
@ -69,7 +69,7 @@ public class AddTaggedHashesToHashDb implements GeneralReportModule {
progressPanel.start();
progressPanel.updateStatusLabel("Adding hashes...");
HashDatabase hashSet = configPanel.getSelectedHashDatabase();
HashDb hashSet = configPanel.getSelectedHashDatabase();
if (hashSet != null) {
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"/>
</Events>
<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>
</Component>
<Component class="javax.swing.JButton" name="configureHashDatabasesButton">

View File

@ -35,11 +35,11 @@ import javax.swing.ListModel;
import javax.swing.event.ListDataListener;
import org.sleuthkit.autopsy.casemodule.Case;
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.HashLookupSettingsPanel;
import org.sleuthkit.datamodel.TagName;
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
@ -52,7 +52,7 @@ class AddTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel {
private final Map<String, Boolean> tagNameSelections = new LinkedHashMap<>();
private final TagNamesListModel tagsNamesListModel = new TagNamesListModel();
private final TagsNamesListCellRenderer tagsNamesRenderer = new TagsNamesListCellRenderer();
private HashDatabase selectedHashSet = null;
private HashDb selectedHashSet = null;
AddTaggedHashesToHashDbConfigPanel() {
initComponents();
@ -107,9 +107,9 @@ class AddTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel {
// Get the updateable hash databases and add their hash set names to the
// JComboBox component.
List<HashDatabase> updateableHashSets = HashDbManager.getInstance().getUpdateableHashDatabases();
List<HashDb> updateableHashSets = HashDbManager.getInstance().getUpdateableHashSets();
if (!updateableHashSets.isEmpty()) {
for (HashDatabase hashDb : updateableHashSets) {
for (HashDb hashDb : updateableHashSets) {
hashSetsComboBox.addItem(hashDb);
}
hashSetsComboBox.setEnabled(true);
@ -138,7 +138,7 @@ class AddTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel {
*
* @return A HashDb object representing the database or null.
*/
HashDatabase getSelectedHashDatabase() {
HashDb getSelectedHashDatabase() {
return selectedHashSet;
}
@ -286,7 +286,7 @@ class AddTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel {
}//GEN-LAST:event_selectAllButtonActionPerformed
private void hashSetsComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_hashSetsComboBoxActionPerformed
selectedHashSet = (HashDatabase)hashSetsComboBox.getSelectedItem();
selectedHashSet = (HashDb)hashSetsComboBox.getSelectedItem();
}//GEN-LAST:event_hashSetsComboBoxActionPerformed
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
private javax.swing.JButton configureHashDatabasesButton;
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 jLabel2;
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.Test;
public class IntestFileFiltersTest {
public class IngestFileFiltersTest {
public IntestFileFiltersTest() {
public IngestFileFiltersTest() {
}
@BeforeClass

View File

@ -18,21 +18,34 @@
*/
package org.sleuthkit.autopsy.experimental.autoingest;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.openide.util.Lookup;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.LocalDiskDSProcessor;
import org.sleuthkit.autopsy.casemodule.LocalFilesDSProcessor;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import static org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.TimeStampUtils;
import org.sleuthkit.datamodel.Content;
/*
* A runnable that adds an archive data source as well as data sources
* contained in the archive to the case database.
* A runnable that adds an archive data source as well as data sources contained
* in the archive to the case database.
*/
class AddArchiveTask implements Runnable {
@ -42,6 +55,7 @@ class AddArchiveTask implements Runnable {
private final DataSourceProcessorProgressMonitor progressMonitor;
private final DataSourceProcessorCallback callback;
private boolean criticalErrorOccurred;
private final Object archiveDspLock;
private static final String ARCHIVE_EXTRACTOR_MODULE_OUTPUT_DIR = "Archive Extractor";
@ -49,19 +63,20 @@ class AddArchiveTask implements Runnable {
* Constructs a runnable task that adds an archive as well as data sources
* contained in the archive to the case database.
*
* @param deviceId An ASCII-printable identifier for the device associated
* with the data source that is intended to be unique across multiple cases
* (e.g., a UUID).
* @param archivePath Path to the archive file.
* @param deviceId An ASCII-printable identifier for the device
* associated with the data source that is intended
* to be unique across multiple cases (e.g., a UUID).
* @param archivePath Path to the archive file.
* @param progressMonitor Progress monitor to report progress during
* processing.
* @param callback Callback to call when processing is done.
* processing.
* @param callback Callback to call when processing is done.
*/
AddArchiveTask(String deviceId, String archivePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
this.deviceId = deviceId;
this.archivePath = archivePath;
this.callback = callback;
this.progressMonitor = progressMonitor;
this.archiveDspLock = new Object();
}
/**
@ -69,39 +84,172 @@ class AddArchiveTask implements Runnable {
*/
@Override
public void run() {
progressMonitor.setIndeterminate(true);
List<String> errorMessages = new ArrayList<>();
List<Content> newDataSources = new ArrayList<>();
DataSourceProcessorCallback.DataSourceProcessorResult result;
if (!ArchiveUtil.isArchive(Paths.get(archivePath))) {
criticalErrorOccurred = true;
logger.log(Level.SEVERE, String.format("Input data source is not a valid datasource: %s", archivePath)); //NON-NLS
errorMessages.add("Input data source is not a valid datasource: " + archivePath);
errorMessages.add("Input data source is not a valid datasource: " + archivePath);
result = DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS;
callback.done(result, errorMessages, newDataSources);
}
logger.log(Level.INFO, "Using Archive Extractor DSP to process archive {0} ", archivePath);
// extract the archive and pass the extracted folder as input
Path destinationFolder = Paths.get("");
try {
Case currentCase = Case.getCurrentCase();
// get file name without full path or extension
String dataSourceFileNameNoExt = FilenameUtils.getBaseName(archivePath);
// create folder to extract archive to
destinationFolder = Paths.get(currentCase.getModuleDirectory(), ARCHIVE_EXTRACTOR_MODULE_OUTPUT_DIR, dataSourceFileNameNoExt + "_" + TimeStampUtils.createTimeStamp());
destinationFolder.toFile().mkdirs();
Path destinationFolder = createDirectoryForFile(archivePath, currentCase.getModuleDirectory());
if (destinationFolder.toString().isEmpty()) {
// unable to create directory
criticalErrorOccurred = true;
errorMessages.add(String.format("Unable to create directory {0} to extract archive {1} ", new Object[]{destinationFolder.toString(), archivePath}));
logger.log(Level.SEVERE, String.format("Unable to create directory {0} to extract archive {1} ", new Object[]{destinationFolder.toString(), archivePath}));
return;
}
// extract contents of ZIP archive into destination folder
//ArchiveUtil.unpackArchiveFile(archivePath, destinationFolder.toString());
// extract contents of ZIP archive into destination folder
progressMonitor.setProgressText(String.format("Extracting archive contents to: %s", destinationFolder.toString()));
List<String> extractedFiles = ArchiveUtil.unpackArchiveFile(archivePath, destinationFolder.toString());
int numExtractedFilesRemaining = extractedFiles.size();
// lookup all AutomatedIngestDataSourceProcessors so that we only do it once.
// LocalDisk, LocalFiles, and ArchiveDSP are removed from the list.
List<AutoIngestDataSourceProcessor> processorCandidates = getListOfValidDataSourceProcessors();
// do processing
for (String file : extractedFiles) {
// we only care about files, skip directories
File fileObject = new File(file);
if (fileObject.isDirectory()) {
numExtractedFilesRemaining--;
continue;
}
// identify all "valid" DSPs that can process this file
List<AutoIngestDataSourceProcessor> validDataSourceProcessors = getDataSourceProcessorsForFile(Paths.get(file), errorMessages, processorCandidates);
if (validDataSourceProcessors.isEmpty()) {
continue;
}
// identified a "valid" data source within the archive
progressMonitor.setProgressText(String.format("Adding: %s", file));
/*
* NOTE: we have to move the valid data sources to a separate
* folder and then add the data source from that folder. This is
* necessary because after all valid data sources have been
* identified, we are going to add the remaining extracted
* contents of the archive as a single logical file set. Hence,
* if we do not move the data sources out of the extracted
* contents folder, those data source files will get added twice
* and can potentially result in duplicate keyword hits.
*/
Path newFolder = createDirectoryForFile(file, currentCase.getModuleDirectory());
if (newFolder.toString().isEmpty()) {
// unable to create directory
criticalErrorOccurred = true;
errorMessages.add(String.format("Unable to create directory {0} to extract content of archive {1} ", new Object[]{newFolder.toString(), archivePath}));
logger.log(Level.SEVERE, String.format("Unable to create directory {0} to extract content of archive {1} ", new Object[]{newFolder.toString(), archivePath}));
return;
}
// Copy it to a different folder
FileUtils.copyFileToDirectory(fileObject, newFolder.toFile());
Path newFilePath = Paths.get(newFolder.toString(), FilenameUtils.getName(file));
// Try each DSP in decreasing order of confidence
boolean success = false;
for (AutoIngestDataSourceProcessor selectedProcessor : validDataSourceProcessors) {
logger.log(Level.INFO, "Using {0} to process extracted file {1} ", new Object[]{selectedProcessor.getDataSourceType(), file});
synchronized (archiveDspLock) {
try {
UUID taskId = UUID.randomUUID();
currentCase.notifyAddingDataSource(taskId);
AutoIngestDataSource internalDataSource = new AutoIngestDataSource(deviceId, newFilePath);
DataSourceProcessorCallback internalArchiveDspCallBack = new AddDataSourceCallback(currentCase, internalDataSource, taskId, archiveDspLock);
selectedProcessor.process(deviceId, newFilePath, progressMonitor, internalArchiveDspCallBack);
archiveDspLock.wait();
// at this point we got the content object(s) from the current DSP.
// check whether the data source was processed successfully
if ((internalDataSource.getResultDataSourceProcessorResultCode() == CRITICAL_ERRORS)
|| internalDataSource.getContent().isEmpty()) {
// move onto the the next DSP that can process this data source
continue;
}
// if we are here it means the data source was addedd successfully
success = true;
newDataSources.addAll(internalDataSource.getContent());
// skip all other DSPs for this data source
break;
} catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) {
// 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
// the data source which each DSP on the list.
criticalErrorOccurred = true;
errorMessages.add(ex.getMessage());
logger.log(Level.SEVERE, "Exception while processing {0} with data source processor {1}", new Object[]{newFilePath.toString(), selectedProcessor.getDataSourceType()});
}
}
}
if (success) {
// one of the DSPs successfully processed the data source. delete the
// copy of the data source in the original extracted archive folder.
// otherwise the data source is going to be added again as a logical file.
numExtractedFilesRemaining--;
FileUtils.deleteQuietly(fileObject);
} else {
// none of the DSPs were able to process the data source. delete the
// copy of the data source in the temporary folder. the data source is
// going to be added as a logical file with the rest of the extracted contents.
FileUtils.deleteQuietly(newFolder.toFile());
}
}
// after all archive contents have been examined (and moved to separate folders if necessary),
// add remaining extracted contents as one logical file set
if (numExtractedFilesRemaining > 0) {
progressMonitor.setProgressText(String.format("Adding: %s", destinationFolder.toString()));
logger.log(Level.INFO, "Adding directory {0} as logical file set", destinationFolder.toString());
synchronized (archiveDspLock) {
UUID taskId = UUID.randomUUID();
currentCase.notifyAddingDataSource(taskId);
AutoIngestDataSource internalDataSource = new AutoIngestDataSource(deviceId, destinationFolder);
DataSourceProcessorCallback internalArchiveDspCallBack = new AddDataSourceCallback(currentCase, internalDataSource, taskId, archiveDspLock);
// folder where archive was extracted to
List<String> pathsList = new ArrayList<>();
pathsList.add(destinationFolder.toString());
// use archive file name as the name of the logical file set
String archiveFileName = FilenameUtils.getName(archivePath);
LocalFilesDSProcessor localFilesDSP = new LocalFilesDSProcessor();
localFilesDSP.run(deviceId, archiveFileName, pathsList, progressMonitor, internalArchiveDspCallBack);
archiveDspLock.wait();
// at this point we got the content object(s) from the current DSP
newDataSources.addAll(internalDataSource.getContent());
}
}
} catch (Exception ex) {
criticalErrorOccurred = true;
errorMessages.add(ex.getMessage());
logger.log(Level.SEVERE, String.format("Critical error occurred while extracting archive %s", archivePath), ex); //NON-NLS
} finally {
logger.log(Level.INFO, "Finished processing of archive {0}", archivePath);
progressMonitor.setProgress(100);
if (criticalErrorOccurred) {
result = DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS;
} else if (!errorMessages.isEmpty()) {
@ -113,10 +261,78 @@ class AddArchiveTask implements Runnable {
}
}
/*
* Attempts to cancel adding the archive to the case database.
/**
* Get a list of data source processors. LocalDisk, LocalFiles, and
* ArchiveDSP are removed from the list.
*
* @return List of data source processors
*/
public void cancelTask() {
private List<AutoIngestDataSourceProcessor> getListOfValidDataSourceProcessors() {
Collection<? extends AutoIngestDataSourceProcessor> processorCandidates = Lookup.getDefault().lookupAll(AutoIngestDataSourceProcessor.class);
List<AutoIngestDataSourceProcessor> validDataSourceProcessors = processorCandidates.stream().collect(Collectors.toList());
for (Iterator<AutoIngestDataSourceProcessor> iterator = validDataSourceProcessors.iterator(); iterator.hasNext();) {
AutoIngestDataSourceProcessor selectedProcessor = iterator.next();
// skip local files and local disk DSPs, only looking for "valid" data sources.
// also skip nested archive files, those will be ingested as logical files and extracted during ingest
if ((selectedProcessor instanceof LocalDiskDSProcessor)
|| (selectedProcessor instanceof LocalFilesDSProcessor)
|| (selectedProcessor instanceof ArchiveExtractorDSProcessor)) {
iterator.remove();
}
}
return validDataSourceProcessors;
}
/**
* Get a list of data source processors that can process the data source of
* interest. The list is sorted by confidence in decreasing order.
*
* @param dataSourcePath Full path to the data source
* @param errorMessages List<String> for error messages
* @param errorMessages List of AutoIngestDataSourceProcessor to try
*
* @return Ordered list of applicable DSPs
*/
private List<AutoIngestDataSourceProcessor> getDataSourceProcessorsForFile(Path dataSourcePath, List<String> errorMessages,
List<AutoIngestDataSourceProcessor> processorCandidates) {
// Get an ordered list of data source processors to try
List<AutoIngestDataSourceProcessor> validDataSourceProcessorsForFile = Collections.emptyList();
try {
validDataSourceProcessorsForFile = DataSourceProcessorUtility.getOrderedListOfDataSourceProcessors(dataSourcePath, processorCandidates);
} catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) {
criticalErrorOccurred = true;
errorMessages.add(ex.getMessage());
logger.log(Level.SEVERE, String.format("Critical error occurred while extracting archive %s", archivePath), ex); //NON-NLS
return Collections.emptyList();
}
return validDataSourceProcessorsForFile;
}
/**
* Create a directory in ModuleOutput folder based on input file name. A
* time stamp is appended to the directory name.
*
* @param fileName File name
* @param baseDirectory Base directory. Typically the case output directory.
*
* @return Full path to the new directory
*/
private Path createDirectoryForFile(String fileName, String baseDirectory) {
// get file name without full path or extension
String fileNameNoExt = FilenameUtils.getBaseName(fileName);
// create folder to extract archive to
Path newFolder = Paths.get(baseDirectory, ARCHIVE_EXTRACTOR_MODULE_OUTPUT_DIR, fileNameNoExt + "_" + TimeStampUtils.createTimeStamp());
if (newFolder.toFile().mkdirs() == false) {
// unable to create directory
return Paths.get("");
}
return newFolder;
}
}

View File

@ -35,7 +35,7 @@ import org.sleuthkit.datamodel.Content;
class AddDataSourceCallback extends DataSourceProcessorCallback {
private final Case caseForJob;
private final DataSource dataSourceInfo;
private final AutoIngestDataSource dataSourceInfo;
private final UUID taskId;
private final Object lock;
@ -48,7 +48,7 @@ class AddDataSourceCallback extends DataSourceProcessorCallback {
* @param dataSourceInfo The data source
* @param taskId The task id to associate with ingest job events.
*/
AddDataSourceCallback(Case caseForJob, DataSource dataSourceInfo, UUID taskId, Object lock) {
AddDataSourceCallback(Case caseForJob, AutoIngestDataSource dataSourceInfo, UUID taskId, Object lock) {
this.caseForJob = caseForJob;
this.dataSourceInfo = dataSourceInfo;
this.taskId = taskId;

View File

@ -18,13 +18,15 @@
*/
package org.sleuthkit.autopsy.experimental.autoingest;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.nio.file.Path;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.JPanel;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
import org.openide.util.lookup.ServiceProviders;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
@ -35,13 +37,12 @@ import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
* add data source wizard. It also provides a run method overload to allow it to
* be used independently of the wizard.
*/
//@ServiceProviders(value={
// @ServiceProvider(service=DataSourceProcessor.class),
// @ServiceProvider(service=AutoIngestDataSourceProcessor.class)}
//)
@ServiceProviders(value={
@ServiceProvider(service=AutoIngestDataSourceProcessor.class)}
)
@NbBundle.Messages({
"ArchiveDSP.dsType.text=Archive file"})
public class ArchiveExtractorDSProcessor implements DataSourceProcessor, AutoIngestDataSourceProcessor {
public class ArchiveExtractorDSProcessor implements AutoIngestDataSourceProcessor {
private final static String DATA_SOURCE_TYPE = Bundle.ArchiveDSP_dsType_text();
@ -50,6 +51,8 @@ public class ArchiveExtractorDSProcessor implements DataSourceProcessor, AutoIng
private String archivePath;
private boolean setDataSourceOptionsCalled;
private final ExecutorService jobProcessingExecutor;
private static final String ARCHIVE_DSP_THREAD_NAME = "Archive-DSP-%d";
private AddArchiveTask addArchiveTask;
/**
@ -60,6 +63,7 @@ public class ArchiveExtractorDSProcessor implements DataSourceProcessor, AutoIng
*/
public ArchiveExtractorDSProcessor() {
configPanel = ArchiveFilePanel.createInstance(ArchiveExtractorDSProcessor.class.getName(), ArchiveUtil.getArchiveFilters());
jobProcessingExecutor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(ARCHIVE_DSP_THREAD_NAME).build());
}
@Override
@ -151,21 +155,15 @@ public class ArchiveExtractorDSProcessor implements DataSourceProcessor, AutoIng
*/
public void run(String deviceId, String archivePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
addArchiveTask = new AddArchiveTask(deviceId, archivePath, progressMonitor, callback);
new Thread(addArchiveTask).start();
jobProcessingExecutor.submit(addArchiveTask);
}
/**
* Requests cancellation of the background task that adds a data source to
* the case database, after the task is started using the run method. This
* is a "best effort" cancellation, with no guarantees that the case
* database will be unchanged. If cancellation succeeded, the list of new
* data sources returned by the background task will be empty.
* This DSP is a service to AutoIngestDataSourceProcessor only. Hence it is
* only used by AIM. AIM currently doesn't support DSP cancellation.
*/
@Override
public void cancel() {
if (null != addArchiveTask) {
addArchiveTask.cancelTask();
}
}
@Override
@ -175,50 +173,4 @@ public class ArchiveExtractorDSProcessor implements DataSourceProcessor, AutoIng
configPanel.reset();
setDataSourceOptionsCalled = false;
}
/**
* Extracts the contents of a ZIP archive submitted as a data source to a
* subdirectory of the auto ingest module output directory.
*
* @throws IOException if there is a problem extracting the data source from
* the archive.
private static Path extractDataSource(Path outputDirectoryPath, Path dataSourcePath) throws IOException {
String dataSourceFileNameNoExt = FilenameUtils.removeExtension(dataSourcePath.getFileName().toString());
Path destinationFolder = Paths.get(outputDirectoryPath.toString(),
AUTO_INGEST_MODULE_OUTPUT_DIR,
dataSourceFileNameNoExt + "_" + TimeStampUtils.createTimeStamp());
Files.createDirectories(destinationFolder);
int BUFFER_SIZE = 524288; // Read/write 500KB at a time
File sourceZipFile = dataSourcePath.toFile();
ZipFile zipFile;
zipFile = new ZipFile(sourceZipFile, ZipFile.OPEN_READ);
Enumeration<? extends ZipEntry> zipFileEntries = zipFile.entries();
try {
while (zipFileEntries.hasMoreElements()) {
ZipEntry entry = zipFileEntries.nextElement();
String currentEntry = entry.getName();
File destFile = new File(destinationFolder.toString(), currentEntry);
destFile = new File(destinationFolder.toString(), destFile.getName());
File destinationParent = destFile.getParentFile();
destinationParent.mkdirs();
if (!entry.isDirectory()) {
BufferedInputStream is = new BufferedInputStream(zipFile.getInputStream(entry));
int currentByte;
byte data[] = new byte[BUFFER_SIZE];
try (FileOutputStream fos = new FileOutputStream(destFile); BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER_SIZE)) {
currentByte = is.read(data, 0, BUFFER_SIZE);
while (currentByte != -1) {
dest.write(data, 0, currentByte);
currentByte = is.read(data, 0, BUFFER_SIZE);
}
}
}
}
} finally {
zipFile.close();
}
return destinationFolder;
} */
}

View File

@ -214,10 +214,11 @@ final class ArchiveUtil {
* @param destinationFolder Path to directory where results will be
* extracted to.
*
* @return List of file names contained within archive
* @throws
* ArchiveExtractionException
*/
static void unpackArchiveFile(String archiveFilePath, String destinationFolder) throws ArchiveExtractionException {
static List<String> unpackArchiveFile(String archiveFilePath, String destinationFolder) throws ArchiveExtractionException {
if (!SevenZip.isInitializedSuccessfully() && (SevenZip.getLastInitializationException() == null)) {
try {
SevenZip.initSevenZipFromPlatformJAR();
@ -225,6 +226,7 @@ final class ArchiveUtil {
throw new ArchiveExtractionException("Unable to initialize 7Zip libraries", ex);
}
}
List<String> files = new ArrayList<>();
ISevenZipInArchive inArchive = null;
try {
RandomAccessFile randomAccessFile = new RandomAccessFile(new File(archiveFilePath), "r");
@ -251,6 +253,8 @@ final class ArchiveUtil {
}
}
}
// keep track of extracted files
files.add(fullPath.toString());
}
} catch (Exception ex) {
throw new ArchiveExtractionException("Exception while unpacking archive contents", ex);
@ -263,6 +267,7 @@ final class ArchiveUtil {
throw new ArchiveExtractionException("Exception while closing the archive", ex);
}
}
return files;
}
/**

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

@ -17,46 +17,22 @@
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" 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="lbPending" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="pendingScrollPane" min="-2" pref="920" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="bnPrioritizeCase" max="32767" attributes="0"/>
<Component id="bnPrioritizeJob" max="32767" attributes="0"/>
</Group>
</Group>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="bnPause" linkSize="1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
<Component id="bnRefresh" linkSize="1" min="-2" pref="100" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
<Component id="bnOptions" linkSize="1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
<Component id="bnOpenLogDir" linkSize="1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
<Component id="bnExit" linkSize="1" min="-2" pref="94" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="runningScrollPane" min="-2" pref="920" max="-2" attributes="0"/>
<Component id="completedScrollPane" min="-2" pref="920" max="-2" attributes="0"/>
</Group>
<Component id="bnPause" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="bnCancelJob" linkSize="1" pref="117" max="32767" attributes="0"/>
<Component id="bnShowProgress" linkSize="1" pref="116" max="32767" attributes="0"/>
<Component id="bnCancelModule" linkSize="1" alignment="0" pref="117" max="32767" attributes="0"/>
<Component id="bnDeleteCase" linkSize="1" alignment="0" pref="117" max="32767" attributes="0"/>
<Component id="bnShowCaseLog" max="32767" attributes="0"/>
<Component id="bnReprocessJob" alignment="0" max="32767" attributes="0"/>
</Group>
<Component id="bnRefresh" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="bnOptions" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="bnOpenLogDir" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="bnClusterMetrics" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="bnExit" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="lbStatus" min="-2" max="-2" attributes="0"/>
@ -73,8 +49,36 @@
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="lbPending" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="runningScrollPane" min="-2" pref="1021" max="-2" attributes="0"/>
<Component id="completedScrollPane" min="-2" pref="1021" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="bnCancelJob" linkSize="1" max="32767" attributes="0"/>
<Component id="bnShowProgress" linkSize="1" max="32767" attributes="0"/>
<Component id="bnCancelModule" linkSize="1" alignment="0" max="32767" attributes="0"/>
<Component id="bnDeleteCase" linkSize="1" alignment="0" max="32767" attributes="0"/>
<Component id="bnShowCaseLog" max="32767" attributes="0"/>
<Component id="bnReprocessJob" alignment="0" max="32767" attributes="0"/>
</Group>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="pendingScrollPane" min="-2" pref="1021" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="bnPrioritizeCase" max="32767" attributes="0"/>
<Component id="bnPrioritizeJob" max="32767" attributes="0"/>
</Group>
</Group>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -99,9 +103,9 @@
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="82" max="-2" attributes="0"/>
<Component id="bnPrioritizeCase" min="-2" max="-2" attributes="0"/>
<Component id="bnPrioritizeCase" linkSize="2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="bnPrioritizeJob" min="-2" max="-2" attributes="0"/>
<Component id="bnPrioritizeJob" linkSize="2" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
@ -135,16 +139,13 @@
<EmptySpace max="-2" attributes="0"/>
<Component id="completedScrollPane" min="-2" pref="179" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
<Component id="bnExit" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnOpenLogDir" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="bnPause" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnRefresh" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnOptions" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="bnPause" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnRefresh" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnOptions" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnOpenLogDir" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnClusterMetrics" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnExit" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
@ -234,6 +235,15 @@
<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.bnCancelJob.toolTipText" 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="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnCancelJobActionPerformed"/>
@ -247,6 +257,15 @@
<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.bnDeleteCase.toolTipText" 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="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnDeleteCaseActionPerformed"/>
@ -290,6 +309,15 @@
<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.bnRefresh.toolTipText" 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="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnRefreshActionPerformed"/>
@ -303,6 +331,15 @@
<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.bnCancelModule.toolTipText" 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="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnCancelModuleActionPerformed"/>
@ -316,6 +353,15 @@
<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.bnExit.toolTipText" 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="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnExitActionPerformed"/>
@ -330,6 +376,15 @@
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnOptions.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnOptionsActionPerformed"/>
@ -343,6 +398,15 @@
<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.bnShowProgress.toolTipText" 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="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnShowProgressActionPerformed"/>
@ -356,6 +420,15 @@
<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.bnPause.toolTipText" 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="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnPauseActionPerformed"/>
@ -369,6 +442,15 @@
<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.bnPrioritizeCase.toolTipText" 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="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnPrioritizeCaseActionPerformed"/>
@ -382,6 +464,15 @@
<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.bnShowCaseLog.toolTipText" 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="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnShowCaseLogActionPerformed"/>
@ -422,6 +513,15 @@
<Property name="actionCommand" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnPrioritizeJob.actionCommand" 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="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnPrioritizeJobActionPerformed"/>
@ -456,20 +556,57 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnOpenLogDir.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="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnOpenLogDirActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="bnClusterMetrics">
<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="AutoIngestControlPanel.bnClusterMetrics.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="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnClusterMetricsActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="bnReprocessJob">
<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="AutoIngestControlPanel.bnReprocessJob.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="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnReprocessJobActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Form>
</Form>

View File

@ -39,7 +39,6 @@ import javax.swing.DefaultListSelectionModel;
import java.awt.Color;
import java.beans.PropertyChangeEvent;
import java.io.File;
import java.util.Collections;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
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.NetworkUtils;
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.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
@ -71,6 +73,7 @@ import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestManager.JobsSnaps
* one such panel per node.
*/
@Messages({
"AutoIngestControlPanel.bnClusterMetrics.text=Cluster Metrics",
"AutoIngestControlPanel.bnPause.text=Pause",
"AutoIngestControlPanel.bnPause.paused=Paused",
"AutoIngestControlPanel.bnPause.running=Running",
@ -114,7 +117,7 @@ import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestManager.JobsSnaps
"AutoIngestControlPanel.bnPrioritizeJob.actionCommand=<AutoIngestControlPanel.bnPrioritizeJob.text>",
"AutoIngestControlPanel.lbServicesStatus.text=Services Status:",
"AutoIngestControlPanel.tbServicesStatusMessage.text=",
"AutoIngestControlPanel.bnOpenLogDir.text=Open System Logs Directory",
"AutoIngestControlPanel.bnOpenLogDir.text=Open System Logs Folder",
"AutoIngestControlPanel.bnReprocessJob.text=Reprocess Job",
"AutoIngestControlPanel.bnPrioritizeFolder.label=<AutoIngestControlPanel.bnPrioritizeJob.text>",
"AutoIngestControlPanel.Cancelling=Cancelling...",
@ -138,6 +141,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
private static final int GENERIC_COL_MAX_WIDTH = 2000;
private static final int PENDING_TABLE_COL_PREFERRED_WIDTH = 280;
private static final int RUNNING_TABLE_COL_PREFERRED_WIDTH = 175;
private static final int PRIORITY_COLUMN_PREFERRED_WIDTH = 60;
private static final int PRIORITY_COLUMN_MAX_WIDTH = 150;
private static final int ACTIVITY_TIME_COL_MIN_WIDTH = 250;
private static final int ACTIVITY_TIME_COL_MAX_WIDTH = 450;
private static final int TIME_COL_MIN_WIDTH = 30;
@ -177,6 +182,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
* ordinal or a column header string.
*/
@Messages({
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority=Prioritized",
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.Case=Case",
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.ImageFolder=Data Source",
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.HostName=Host Name",
@ -203,8 +209,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
STATUS(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Status")),
CASE_DIRECTORY_PATH(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.CaseFolder")),
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 JobsTableModelColumns(String header) {
@ -227,7 +233,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
STAGE_TIME.getColumnHeader(),
CASE_DIRECTORY_PATH.getColumnHeader(),
IS_LOCAL_JOB.getColumnHeader(),
MANIFEST_FILE_PATH.getColumnHeader()};
MANIFEST_FILE_PATH.getColumnHeader(),
PRIORITY.getColumnHeader()};
}
/**
@ -259,32 +266,11 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
manager = AutoIngestManager.getInstance();
pendingTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) {
private static final long serialVersionUID = 1L;
pendingTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0);
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
runningTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0);
runningTableModel = new DefaultTableModel(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;
}
};
completedTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0);
initComponents(); // Generated code.
setServicesStatusMessage();
@ -292,7 +278,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
initRunningJobsTable();
initCompletedJobsTable();
initButtons();
completedTable.getRowSorter().toggleSortOrder(JobsTableModelColumns.COMPLETED_TIME.ordinal());
/*
* Must set this flag, otherwise pop up menus don't close properly.
*/
@ -412,10 +398,16 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
column.setPreferredWidth(TIME_COL_PREFERRED_WIDTH);
column.setWidth(TIME_COL_PREFERRED_WIDTH);
column = pendingTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader());
column.setCellRenderer(new PrioritizedIconCellRenderer());
column.setMaxWidth(PRIORITY_COLUMN_MAX_WIDTH);
column.setPreferredWidth(PRIORITY_COLUMN_PREFERRED_WIDTH);
column.setWidth(PRIORITY_COLUMN_PREFERRED_WIDTH);
/**
* 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
@ -454,7 +446,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.IS_LOCAL_JOB.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.
*/
@ -524,9 +516,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
}
private void updateRunningTableButtonsBasedOnSelectedRow() {
int row = runningTable.getSelectedRow();
int row = runningTable.convertRowIndexToModel(runningTable.getSelectedRow());
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);
return;
}
@ -544,13 +536,13 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
* 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.HOST_NAME.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.STAGE.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.STAGE_TIME.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.MANIFEST_FILE_PATH.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader()));
/*
* Set up a column to display the cases associated with the jobs.
*/
@ -596,16 +588,16 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
* renderer that will choose an icon to represent the job status.
*/
column = completedTable.getColumn(JobsTableModelColumns.STATUS.getColumnHeader());
column.setCellRenderer(new CaseStatusIconCellRenderer());
column.setCellRenderer(new StatusIconCellRenderer());
column.setMinWidth(STATUS_COL_MIN_WIDTH);
column.setMaxWidth(STATUS_COL_MAX_WIDTH);
column.setPreferredWidth(STATUS_COL_PREFERRED_WIDTH);
column.setWidth(STATUS_COL_PREFERRED_WIDTH);
/*
* 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
@ -982,7 +974,6 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
List<AutoIngestJob> completedJobs = new ArrayList<>();
manager.getJobs(pendingJobs, runningJobs, completedJobs);
// Sort the completed jobs list by completed date
Collections.sort(completedJobs, new AutoIngestJob.CompletedDateDescendingComparator());
EventQueue.invokeLater(new RefreshComponentsTask(pendingJobs, runningJobs, completedJobs));
}
}
@ -1030,9 +1021,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
*/
if (null != pendingJobs) {
Path currentRow = getSelectedEntry(pendingTable, pendingTableModel);
refreshTable(pendingJobs, pendingTableModel, null);
setSelectedEntry(pendingTable, pendingTableModel, currentRow);
Path currentRow = getSelectedEntry(pendingTable);
refreshTable(pendingJobs, (DefaultTableModel) pendingTable.getModel(), null);
setSelectedEntry(pendingTable, currentRow);
}
if (null != runningJobs) {
@ -1041,15 +1032,15 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
} else {
updateRunningTableButtonsBasedOnSelectedRow();
}
Path currentRow = getSelectedEntry(runningTable, runningTableModel);
refreshTable(runningJobs, runningTableModel, null);
setSelectedEntry(runningTable, runningTableModel, currentRow);
Path currentRow = getSelectedEntry(runningTable);
refreshTable(runningJobs, (DefaultTableModel) runningTable.getModel(), null);
setSelectedEntry(runningTable, currentRow);
}
if (null != completedJobs) {
Path currentRow = getSelectedEntry(completedTable, completedTableModel);
refreshTable(completedJobs, completedTableModel, null);
setSelectedEntry(completedTable, completedTableModel, currentRow);
Path currentRow = getSelectedEntry(completedTable);
refreshTable(completedJobs, (DefaultTableModel) completedTable.getModel(), null);
setSelectedEntry(completedTable, currentRow);
}
}
@ -1087,12 +1078,12 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
*
* @return a path representing the current selection
*/
Path getSelectedEntry(JTable table, DefaultTableModel tableModel) {
Path getSelectedEntry(JTable table) {
try {
int currentlySelectedRow = table.getSelectedRow();
int currentlySelectedRow = table.convertRowIndexToModel(table.getSelectedRow());
if (currentlySelectedRow >= 0 && currentlySelectedRow < table.getRowCount()) {
return Paths.get(tableModel.getValueAt(currentlySelectedRow, JobsTableModelColumns.CASE.ordinal()).toString(),
tableModel.getValueAt(currentlySelectedRow, JobsTableModelColumns.DATA_SOURCE.ordinal()).toString());
return Paths.get(table.getModel().getValueAt(currentlySelectedRow, JobsTableModelColumns.CASE.ordinal()).toString(),
table.getModel().getValueAt(currentlySelectedRow, JobsTableModelColumns.DATA_SOURCE.ordinal()).toString());
}
} catch (Exception ignored) {
return null;
@ -1108,12 +1099,12 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
* @param tableModel The tableModel of the table 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) {
try {
for (int row = 0; row < table.getRowCount(); ++row) {
Path temp = Paths.get(tableModel.getValueAt(row, JobsTableModelColumns.CASE.ordinal()).toString(),
tableModel.getValueAt(row, JobsTableModelColumns.DATA_SOURCE.ordinal()).toString());
Path temp = Paths.get(table.getModel().getValueAt(row, JobsTableModelColumns.CASE.ordinal()).toString(),
table.getModel().getValueAt(row, JobsTableModelColumns.DATA_SOURCE.ordinal()).toString());
if (temp.compareTo(path) == 0) { // found it
table.setRowSelectionInterval(row, row);
return;
@ -1152,11 +1143,12 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
job.getProcessingStageStartDate(), // STARTED_TIME
job.getCompletedDate(), // COMPLETED_TIME
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
job.getCaseDirectoryPath(), // CASE_DIRECTORY_PATH
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) {
SYS_LOGGER.log(Level.SEVERE, "Dashboard error refreshing table", ex);
@ -1168,9 +1160,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
*/
private void refreshTables() {
JobsSnapshot jobsSnapshot = manager.getCurrentJobsSnapshot();
refreshTable(jobsSnapshot.getCompletedJobs(), completedTableModel, null);
refreshTable(jobsSnapshot.getPendingJobs(), pendingTableModel, null);
refreshTable(jobsSnapshot.getRunningJobs(), runningTableModel, null);
refreshTable(jobsSnapshot.getCompletedJobs(), (DefaultTableModel) completedTable.getModel(), null);
refreshTable(jobsSnapshot.getPendingJobs(), (DefaultTableModel) pendingTable.getModel(), null);
refreshTable(jobsSnapshot.getRunningJobs(), (DefaultTableModel) runningTable.getModel(), null);
}
/**
@ -1207,6 +1199,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
lbServicesStatus = new javax.swing.JLabel();
tbServicesStatusMessage = new javax.swing.JTextField();
bnOpenLogDir = new javax.swing.JButton();
bnClusterMetrics = new javax.swing.JButton();
bnReprocessJob = new javax.swing.JButton();
pendingTable.setModel(pendingTableModel);
@ -1265,6 +1258,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnCancelJob, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnCancelJob.text")); // NOI18N
bnCancelJob.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnCancelJob.toolTipText")); // NOI18N
bnCancelJob.setMaximumSize(new java.awt.Dimension(162, 23));
bnCancelJob.setMinimumSize(new java.awt.Dimension(162, 23));
bnCancelJob.setPreferredSize(new java.awt.Dimension(162, 23));
bnCancelJob.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnCancelJobActionPerformed(evt);
@ -1273,6 +1269,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnDeleteCase, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnDeleteCase.text")); // NOI18N
bnDeleteCase.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnDeleteCase.toolTipText")); // NOI18N
bnDeleteCase.setMaximumSize(new java.awt.Dimension(162, 23));
bnDeleteCase.setMinimumSize(new java.awt.Dimension(162, 23));
bnDeleteCase.setPreferredSize(new java.awt.Dimension(162, 23));
bnDeleteCase.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnDeleteCaseActionPerformed(evt);
@ -1290,6 +1289,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnRefresh, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnRefresh.text")); // NOI18N
bnRefresh.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnRefresh.toolTipText")); // NOI18N
bnRefresh.setMaximumSize(new java.awt.Dimension(162, 23));
bnRefresh.setMinimumSize(new java.awt.Dimension(162, 23));
bnRefresh.setPreferredSize(new java.awt.Dimension(162, 23));
bnRefresh.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnRefreshActionPerformed(evt);
@ -1298,6 +1300,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnCancelModule, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnCancelModule.text")); // NOI18N
bnCancelModule.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnCancelModule.toolTipText")); // NOI18N
bnCancelModule.setMaximumSize(new java.awt.Dimension(162, 23));
bnCancelModule.setMinimumSize(new java.awt.Dimension(162, 23));
bnCancelModule.setPreferredSize(new java.awt.Dimension(162, 23));
bnCancelModule.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnCancelModuleActionPerformed(evt);
@ -1306,6 +1311,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnExit, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnExit.text")); // NOI18N
bnExit.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnExit.toolTipText")); // NOI18N
bnExit.setMaximumSize(new java.awt.Dimension(162, 23));
bnExit.setMinimumSize(new java.awt.Dimension(162, 23));
bnExit.setPreferredSize(new java.awt.Dimension(162, 23));
bnExit.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnExitActionPerformed(evt);
@ -1315,6 +1323,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnOptions, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnOptions.text")); // NOI18N
bnOptions.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnOptions.toolTipText")); // NOI18N
bnOptions.setEnabled(false);
bnOptions.setMaximumSize(new java.awt.Dimension(162, 23));
bnOptions.setMinimumSize(new java.awt.Dimension(162, 23));
bnOptions.setPreferredSize(new java.awt.Dimension(162, 23));
bnOptions.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnOptionsActionPerformed(evt);
@ -1323,6 +1334,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnShowProgress, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnShowProgress.text")); // NOI18N
bnShowProgress.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnShowProgress.toolTipText")); // NOI18N
bnShowProgress.setMaximumSize(new java.awt.Dimension(162, 23));
bnShowProgress.setMinimumSize(new java.awt.Dimension(162, 23));
bnShowProgress.setPreferredSize(new java.awt.Dimension(162, 23));
bnShowProgress.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnShowProgressActionPerformed(evt);
@ -1331,6 +1345,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnPause, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPause.text")); // NOI18N
bnPause.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPause.toolTipText")); // NOI18N
bnPause.setMaximumSize(new java.awt.Dimension(162, 23));
bnPause.setMinimumSize(new java.awt.Dimension(162, 23));
bnPause.setPreferredSize(new java.awt.Dimension(162, 23));
bnPause.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnPauseActionPerformed(evt);
@ -1339,6 +1356,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnPrioritizeCase, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPrioritizeCase.text")); // NOI18N
bnPrioritizeCase.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPrioritizeCase.toolTipText")); // NOI18N
bnPrioritizeCase.setMaximumSize(new java.awt.Dimension(162, 23));
bnPrioritizeCase.setMinimumSize(new java.awt.Dimension(162, 23));
bnPrioritizeCase.setPreferredSize(new java.awt.Dimension(162, 23));
bnPrioritizeCase.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnPrioritizeCaseActionPerformed(evt);
@ -1347,6 +1367,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnShowCaseLog, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnShowCaseLog.text")); // NOI18N
bnShowCaseLog.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnShowCaseLog.toolTipText")); // NOI18N
bnShowCaseLog.setMaximumSize(new java.awt.Dimension(162, 23));
bnShowCaseLog.setMinimumSize(new java.awt.Dimension(162, 23));
bnShowCaseLog.setPreferredSize(new java.awt.Dimension(162, 23));
bnShowCaseLog.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnShowCaseLogActionPerformed(evt);
@ -1364,6 +1387,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnPrioritizeJob, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPrioritizeJob.text")); // NOI18N
bnPrioritizeJob.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPrioritizeJob.toolTipText")); // NOI18N
bnPrioritizeJob.setActionCommand(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPrioritizeJob.actionCommand")); // NOI18N
bnPrioritizeJob.setMaximumSize(new java.awt.Dimension(162, 23));
bnPrioritizeJob.setMinimumSize(new java.awt.Dimension(162, 23));
bnPrioritizeJob.setPreferredSize(new java.awt.Dimension(162, 23));
bnPrioritizeJob.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnPrioritizeJobActionPerformed(evt);
@ -1379,13 +1405,29 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
tbServicesStatusMessage.setBorder(null);
org.openide.awt.Mnemonics.setLocalizedText(bnOpenLogDir, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnOpenLogDir.text")); // NOI18N
bnOpenLogDir.setMaximumSize(new java.awt.Dimension(162, 23));
bnOpenLogDir.setMinimumSize(new java.awt.Dimension(162, 23));
bnOpenLogDir.setPreferredSize(new java.awt.Dimension(162, 23));
bnOpenLogDir.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnOpenLogDirActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(bnClusterMetrics, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnClusterMetrics.text")); // NOI18N
bnClusterMetrics.setMaximumSize(new java.awt.Dimension(162, 23));
bnClusterMetrics.setMinimumSize(new java.awt.Dimension(162, 23));
bnClusterMetrics.setPreferredSize(new java.awt.Dimension(162, 23));
bnClusterMetrics.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnClusterMetricsActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(bnReprocessJob, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnReprocessJob.text")); // NOI18N
bnReprocessJob.setMaximumSize(new java.awt.Dimension(162, 23));
bnReprocessJob.setMinimumSize(new java.awt.Dimension(162, 23));
bnReprocessJob.setPreferredSize(new java.awt.Dimension(162, 23));
bnReprocessJob.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnReprocessJobActionPerformed(evt);
@ -1399,38 +1441,20 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(lbPending, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(pendingScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 920, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(bnPrioritizeCase, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(bnPrioritizeJob, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(bnPause)
.addGap(18, 18, 18)
.addComponent(bnRefresh, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(bnOptions)
.addGap(18, 18, 18)
.addComponent(bnOpenLogDir)
.addGap(18, 18, 18)
.addComponent(bnExit, javax.swing.GroupLayout.PREFERRED_SIZE, 94, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(runningScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 920, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(completedScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 920, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(bnPause, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(bnCancelJob, javax.swing.GroupLayout.DEFAULT_SIZE, 117, Short.MAX_VALUE)
.addComponent(bnShowProgress, javax.swing.GroupLayout.DEFAULT_SIZE, 116, Short.MAX_VALUE)
.addComponent(bnCancelModule, javax.swing.GroupLayout.DEFAULT_SIZE, 117, Short.MAX_VALUE)
.addComponent(bnDeleteCase, javax.swing.GroupLayout.DEFAULT_SIZE, 117, 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(bnRefresh, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(bnOptions, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(bnOpenLogDir, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(bnClusterMetrics, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(bnExit, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addComponent(lbStatus)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
@ -1441,11 +1465,32 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
.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())
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lbPending)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(runningScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 1021, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(completedScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 1021, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(bnCancelJob, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(bnShowProgress, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(bnCancelModule, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(bnDeleteCase, 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)))
.addGroup(layout.createSequentialGroup()
.addComponent(pendingScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 1021, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(bnPrioritizeCase, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(bnPrioritizeJob, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
);
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {bnCancelJob, bnCancelModule, bnDeleteCase, bnExit, bnOpenLogDir, bnOptions, bnPause, bnRefresh, bnShowProgress});
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {bnCancelJob, bnCancelModule, bnDeleteCase, bnShowProgress});
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -1465,48 +1510,47 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
.addComponent(pendingScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addGap(82, 82, 82)
.addComponent(bnPrioritizeCase)
.addComponent(bnPrioritizeCase, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnPrioritizeJob)))
.addComponent(bnPrioritizeJob, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lbRunning)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(34, 34, 34)
.addComponent(bnShowProgress)
.addComponent(bnShowProgress, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnCancelJob)
.addComponent(bnCancelJob, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnCancelModule))
.addComponent(bnCancelModule, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(runningScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 133, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(68, 68, 68)
.addComponent(bnReprocessJob)
.addComponent(bnReprocessJob, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnDeleteCase)
.addComponent(bnDeleteCase, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnShowCaseLog))
.addComponent(bnShowCaseLog, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lbCompleted)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(completedScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 179, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(bnExit)
.addComponent(bnOpenLogDir))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(bnPause)
.addComponent(bnRefresh)
.addComponent(bnOptions)))))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(bnPause, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(bnRefresh, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(bnOptions, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(bnOpenLogDir, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(bnClusterMetrics, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(bnExit, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))
.addContainerGap())
);
layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {bnCancelJob, bnCancelModule, bnDeleteCase, bnExit, bnOpenLogDir, bnOptions, bnRefresh, bnShowProgress});
layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {bnCancelJob, bnCancelModule, bnClusterMetrics, bnDeleteCase, bnExit, bnOpenLogDir, bnOptions, bnPrioritizeCase, bnPrioritizeJob, bnRefresh, bnShowProgress});
}// </editor-fold>//GEN-END:initComponents
@ -1535,11 +1579,11 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
"AutoIngestControlPanel.DeletionFailed=Deletion failed for job"
})
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;
}
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 = {
org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "ConfirmationDialog.Delete"),
org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "ConfirmationDialog.DoNotDelete")
@ -1556,8 +1600,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
if (reply == JOptionPane.YES_OPTION) {
bnDeleteCase.setEnabled(false);
bnShowCaseLog.setEnabled(false);
if (completedTableModel.getRowCount() > 0 && completedTable.getSelectedRow() >= 0) {
Path caseDirectoryPath = (Path) completedTableModel.getValueAt(completedTable.getSelectedRow(), JobsTableModelColumns.CASE_DIRECTORY_PATH.ordinal());
if (completedTable.getModel().getRowCount() > 0 && completedTable.getSelectedRow() >= 0) {
Path caseDirectoryPath = (Path) completedTable.getModel().getValueAt(completedTable.convertRowIndexToModel(completedTable.getSelectedRow()), JobsTableModelColumns.CASE_DIRECTORY_PATH.ordinal());
completedTable.clearSelection();
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
CaseDeletionResult result = manager.deleteCase(caseName, caseDirectoryPath);
@ -1703,9 +1747,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."})
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));
String caseName = (pendingTableModel.getValueAt(pendingTable.getSelectedRow(), JobsTableModelColumns.CASE.ordinal())).toString();
String caseName = (pendingTable.getModel().getValueAt(pendingTable.convertRowIndexToModel(pendingTable.getSelectedRow()), JobsTableModelColumns.CASE.ordinal())).toString();
try {
manager.prioritizeCase(caseName);
} catch (AutoIngestManager.AutoIngestManagerException ex) {
@ -1731,9 +1776,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
})
private void bnShowCaseLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnShowCaseLogActionPerformed
try {
int selectedRow = completedTable.getSelectedRow();
int selectedRow = completedTable.convertRowIndexToModel(completedTable.getSelectedRow());
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) {
Path pathToLog = AutoIngestJobLogger.getLogPath(caseDirectoryPath);
if (pathToLog.toFile().exists()) {
@ -1762,9 +1807,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
@Messages({"AutoIngestControlPanel.jobPrioritization.errorMessage=An error occurred when prioritizing the job."})
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));
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 {
manager.prioritizeJob(manifestFilePath);
} catch (AutoIngestManager.AutoIngestManagerException ex) {
@ -1791,19 +1836,28 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
}//GEN-LAST:event_bnOpenLogDirActionPerformed
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;
}
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);
refreshTables();
AutoIngestControlPanel.this.setCursor(Cursor.getDefaultCursor());
}//GEN-LAST:event_bnReprocessJobActionPerformed
private void bnClusterMetricsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnClusterMetricsActionPerformed
try {
new AutoIngestMetricsDialog(this.getTopLevelAncestor());
} catch (AutoIngestMetricsDialog.AutoIngestMetricsDialogException ex) {
MessageNotifyUtil.Message.error(ex.getMessage());
}
}//GEN-LAST:event_bnClusterMetricsActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton bnCancelJob;
private javax.swing.JButton bnCancelModule;
private javax.swing.JButton bnClusterMetrics;
private javax.swing.JButton bnDeleteCase;
private javax.swing.JButton bnExit;
private javax.swing.JButton bnOpenLogDir;
@ -1830,4 +1884,33 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
private javax.swing.JTextField tbStatusMessage;
// 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"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="pendingScrollPane" max="32767" attributes="0"/>
<Component id="runningScrollPane" alignment="0" max="32767" attributes="0"/>
<Component id="completedScrollPane" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<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="lbCompleted" 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"/>
<Component id="tbServicesStatusMessage" min="-2" pref="861" max="-2" attributes="0"/>
</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>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Component id="runningScrollPane" alignment="0" max="32767" attributes="0"/>
<Component id="completedScrollPane" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
@ -81,6 +83,7 @@
<Component id="refreshButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="prioritizeJobButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="prioritizeCaseButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="clusterMetricsButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
@ -103,7 +106,6 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestDashboard.pendingTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="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="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
<JTableSelectionModel selectionMode="0"/>
@ -127,7 +129,6 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestDashboard.runningTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="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="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
<JTableSelectionModel selectionMode="0"/>
@ -151,7 +152,6 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestDashboard.completedTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="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="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
<JTableSelectionModel selectionMode="0"/>
@ -255,5 +255,15 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="prioritizeCaseButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="clusterMetricsButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<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>
</Form>

View File

@ -44,17 +44,22 @@ import org.sleuthkit.autopsy.core.ServicesMonitor;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestMonitor.JobsSnapshot;
import org.sleuthkit.autopsy.guiutils.DurationCellRenderer;
import org.sleuthkit.autopsy.guiutils.LongDateCellRenderer;
import org.sleuthkit.autopsy.guiutils.StatusIconCellRenderer;
/**
* A dashboard for monitoring an automated ingest cluster.
*/
public final class AutoIngestDashboard extends JPanel implements Observer {
final class AutoIngestDashboard extends JPanel implements Observer {
private static final long serialVersionUID = 1L;
private static final int GENERIC_COL_MIN_WIDTH = 30;
private static final int GENERIC_COL_MAX_WIDTH = 2000;
private static final int PENDING_TABLE_COL_PREFERRED_WIDTH = 280;
private static final int RUNNING_TABLE_COL_PREFERRED_WIDTH = 175;
private static final int PRIORITY_COLUMN_PREFERRED_WIDTH = 60;
private static final int PRIORITY_COLUMN_MAX_WIDTH = 150;
private static final int STAGE_TIME_COL_MIN_WIDTH = 250;
private static final int STAGE_TIME_COL_MAX_WIDTH = 450;
private static final int TIME_COL_MIN_WIDTH = 30;
@ -100,32 +105,11 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
* Constructs a panel for monitoring an automated ingest cluster.
*/
private AutoIngestDashboard() {
pendingTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) {
private static final long serialVersionUID = 1L;
pendingTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0);
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
runningTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0);
runningTableModel = new DefaultTableModel(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;
}
};
completedTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0);
initComponents();
setServicesStatusMessage();
@ -243,10 +227,15 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
column.setPreferredWidth(TIME_COL_PREFERRED_WIDTH);
column.setWidth(TIME_COL_PREFERRED_WIDTH);
/**
* Prevent sorting when a column header is clicked.
column = pendingTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader());
column.setCellRenderer(new PrioritizedIconCellRenderer());
column.setMaxWidth(PRIORITY_COLUMN_MAX_WIDTH);
column.setPreferredWidth(PRIORITY_COLUMN_PREFERRED_WIDTH);
column.setWidth(PRIORITY_COLUMN_PREFERRED_WIDTH);
/*
* Allow sorting when a column header is clicked.
*/
pendingTable.setAutoCreateRowSorter(false);
pendingTable.setRowSorter(new AutoIngestRowSorter<>(pendingTableModel));
/*
* Create a row selection listener to enable/disable the Prioritize
@ -257,8 +246,8 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
return;
}
int row = pendingTable.getSelectedRow();
boolean enablePrioritizeButtons = (row >= 0 && row < pendingTable.getRowCount());
boolean enablePrioritizeButtons = (row >= 0 && row < pendingTable.getRowCount());
this.prioritizeJobButton.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.MANIFEST_FILE_PATH.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.JOB.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader()));
/*
* Set up a column to display the cases associated with the jobs.
*/
@ -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.MANIFEST_FILE_PATH.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.JOB.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader()));
/*
* Set up a column to display the cases associated with the jobs.
*/
@ -400,16 +389,15 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
* renderer that will choose an icon to represent the job status.
*/
column = completedTable.getColumn(JobsTableModelColumns.STATUS.getColumnHeader());
column.setCellRenderer(new CaseStatusIconCellRenderer());
column.setCellRenderer(new StatusIconCellRenderer());
column.setMinWidth(STATUS_COL_MIN_WIDTH);
column.setMaxWidth(STATUS_COL_MAX_WIDTH);
column.setPreferredWidth(STATUS_COL_PREFERRED_WIDTH);
column.setWidth(STATUS_COL_PREFERRED_WIDTH);
/*
* 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.getCompletedDate(), // COMPLETED_TIME
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
job.getCaseDirectoryPath(), // CASE_DIRECTORY_PATH
job.getManifest().getFilePath(), // MANIFEST_FILE_PATH
job.getPriority(), // PRIORITY
job
});
}
@ -541,6 +530,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
* described by either an enum ordinal or a column header string.
*/
private enum JobsTableModelColumns {
@Messages({"AutoIngestDashboard.JobsTableModel.ColumnHeader.Priority=Prioritized"})
CASE(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Case")),
DATA_SOURCE(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.ImageFolder")),
@ -553,6 +543,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
STATUS(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Status")),
CASE_DIRECTORY_PATH(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.CaseFolder")),
MANIFEST_FILE_PATH(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.ManifestFilePath")),
PRIORITY(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Priority")),
JOB(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Job"));
private final String header;
@ -577,6 +568,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
STAGE_TIME.getColumnHeader(),
CASE_DIRECTORY_PATH.getColumnHeader(),
MANIFEST_FILE_PATH.getColumnHeader(),
PRIORITY.getColumnHeader(),
JOB.getColumnHeader()
};
};
@ -662,12 +654,12 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
tbServicesStatusMessage = new javax.swing.JTextField();
prioritizeJobButton = 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
pendingTable.setModel(pendingTableModel);
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.setSelectionModel(new DefaultListSelectionModel() {
private static final long serialVersionUID = 1L;
@ -685,7 +677,6 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
runningTable.setModel(runningTableModel);
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.setSelectionModel(new DefaultListSelectionModel() {
private static final long serialVersionUID = 1L;
@ -703,7 +694,6 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
completedTable.setModel(completedTableModel);
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.setSelectionModel(new DefaultListSelectionModel() {
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);
this.setLayout(layout);
layout.setHorizontalGroup(
@ -770,24 +767,26 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.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(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lbPending)
.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()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(refreshButton, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
.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)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(prioritizeCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(0, 0, Short.MAX_VALUE))
.addComponent(runningScrollPane, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(completedScrollPane, javax.swing.GroupLayout.Alignment.LEADING))
.addComponent(prioritizeCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(clusterMetricsButton))
.addComponent(lbPending, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lbCompleted, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lbRunning, javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(lbServicesStatus)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(tbServicesStatusMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 861, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
@ -813,7 +812,8 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(refreshButton)
.addComponent(prioritizeJobButton)
.addComponent(prioritizeCaseButton))
.addComponent(prioritizeCaseButton)
.addComponent(clusterMetricsButton))
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
@ -872,7 +872,16 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
}
}//GEN-LAST:event_prioritizeCaseButtonActionPerformed
private void clusterMetricsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_clusterMetricsButtonActionPerformed
try {
new AutoIngestMetricsDialog(this.getTopLevelAncestor());
} catch (AutoIngestMetricsDialog.AutoIngestMetricsDialogException ex) {
MessageNotifyUtil.Message.error(ex.getMessage());
}
}//GEN-LAST:event_clusterMetricsButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton clusterMetricsButton;
private javax.swing.JScrollPane completedScrollPane;
private javax.swing.JTable completedTable;
private javax.swing.JButton jButton1;
@ -890,4 +899,33 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
private javax.swing.JTextField tbServicesStatusMessage;
// End of variables declaration//GEN-END:variables
private class AutoIngestTableModel extends DefaultTableModel {
private static final long serialVersionUID = 1L;
private AutoIngestTableModel(String[] headers, int i) {
super(headers, i);
}
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == JobsTableModelColumns.PRIORITY.ordinal()) {
return Integer.class;
} else if (columnIndex == JobsTableModelColumns.CREATED_TIME.ordinal()
|| columnIndex == JobsTableModelColumns.COMPLETED_TIME.ordinal()
|| columnIndex == JobsTableModelColumns.STARTED_TIME.ordinal()
|| columnIndex == JobsTableModelColumns.STAGE_TIME.ordinal()) {
return Date.class;
} else if (columnIndex == JobsTableModelColumns.STATUS.ordinal()) {
return Boolean.class;
} else {
return super.getColumnClass(columnIndex);
}
}
}
}

View File

@ -25,7 +25,6 @@ import org.openide.util.HelpCtx;
import org.openide.util.NbBundle.Messages;
import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.core.UserPreferences;
import static org.sleuthkit.autopsy.core.UserPreferences.SelectedMode.REVIEW;
import org.sleuthkit.autopsy.coreutils.Logger;
@ActionID(category = "Tools", id = "org.sleuthkit.autopsy.experimental.autoingest.AutoIngestDashboardOpenAction")
@ -39,8 +38,7 @@ public final class AutoIngestDashboardOpenAction extends CallableSystemAction {
@Override
public boolean isEnabled() {
UserPreferences.SelectedMode mode = UserPreferences.getMode();
return (mode == REVIEW);
return (UserPreferences.getIsMultiUserModeEnabled());
}
@Override

View File

@ -26,7 +26,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback
import org.sleuthkit.datamodel.Content;
@ThreadSafe
class DataSource {
class AutoIngestDataSource {
private final String deviceId;
private final Path path;
@ -34,7 +34,7 @@ class DataSource {
private List<String> errorMessages;
private List<Content> content;
DataSource(String deviceId, Path path) {
AutoIngestDataSource(String deviceId, Path path) {
this.deviceId = deviceId;
this.path = path;
}

View File

@ -62,7 +62,9 @@ import org.openide.util.Lookup;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.casemodule.CaseDetails;
import org.sleuthkit.autopsy.casemodule.CaseMetadata;
import org.sleuthkit.autopsy.coordinationservice.CaseNodeData;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
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.AutopsyEventException;
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.FileExporter.FileExportException;
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
* 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 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 int DEFAULT_JOB_PRIORITY = 0;
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 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);
InputDirScanner scanner = new InputDirScanner();
scanner.scan();
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()) {
++maxPriority;
for (AutoIngestJob job : prioritizedJobs) {
int oldPriority = job.getPriority();
job.setPriority(maxPriority);
try {
this.updateCoordinationServiceNode(job);
job.setPriority(maxPriority);
this.updateCoordinationServiceManifestNode(job);
} catch (CoordinationServiceException | InterruptedException ex) {
job.setPriority(oldPriority);
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
* data for the job.
* Bump the priority by one and update the coordination service
* manifest node data for the job.
*/
if (null != prioritizedJob) {
++maxPriority;
int oldPriority = prioritizedJob.getPriority();
prioritizedJob.setPriority(maxPriority);
try {
this.updateCoordinationServiceNode(prioritizedJob);
this.updateCoordinationServiceManifestNode(prioritizedJob);
} catch (CoordinationServiceException | InterruptedException ex) {
prioritizedJob.setPriority(oldPriority);
throw new AutoIngestManagerException("Error updating job priority", ex);
}
prioritizedJob.setPriority(maxPriority);
}
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
* service node data for the job.
* service manifest node data for the job.
*/
if (null != completedJob && !completedJob.getCaseDirectoryPath().toString().isEmpty()) {
try {
@ -661,7 +666,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
completedJob.setCompletedDate(new Date(0));
completedJob.setProcessingStatus(PENDING);
completedJob.setProcessingStage(AutoIngestJob.Stage.PENDING, Date.from(Instant.now()));
updateCoordinationServiceNode(completedJob);
updateCoordinationServiceManifestNode(completedJob);
pendingJobs.add(completedJob);
} catch (CoordinationServiceException 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()));
AutoIngestJob deletedJob = new AutoIngestJob(nodeData);
deletedJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.DELETED);
this.updateCoordinationServiceNode(deletedJob);
this.updateCoordinationServiceManifestNode(deletedJob);
} catch (AutoIngestJobNodeData.InvalidDataException | AutoIngestJobException ex) {
SYS_LOGGER.log(Level.WARNING, String.format("Invalid auto ingest job node data for %s", manifestPath), ex);
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
* passed in. Thus, if the data version of the node has changed, the node
* will be "upgraded" as well as updated.
* Note that a new auto ingest job node data object will be created from the
* job passed in. Thus, if the data version of the node has changed, the
* node will be "upgraded" as well as updated.
*
* @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);
String manifestNodePath = job.getManifest().getFilePath().toString();
byte[] rawData = nodeData.toArray();
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
* scan task executor.
@ -1041,8 +1062,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
if (null != manifest) {
/*
* Update the mapping of case names to manifest paths that is
* used for case deletion.
* Update the mapping of case names to manifest paths that
* is used for case deletion.
*/
String caseName = manifest.getCaseName();
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,
* or do crashed job recovery, as required.
* Add a job to the pending jobs queue, the completed jobs
* list, or do crashed job recovery, as required.
*/
try {
byte[] rawData = coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString());
@ -1077,7 +1098,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
break;
case DELETED:
/*
* Ignore jobs marked as "deleted."
* Ignore jobs marked as "deleted."
*/
break;
default:
@ -1147,8 +1168,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
}
/*
* Try to upgrade/update the coordination service node data for
* the job.
* Try to upgrade/update the coordination service manifest node
* data for the job.
*
* An exclusive lock is obtained before doing so because another
* 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())) {
if (null != manifestLock) {
updateCoordinationServiceNode(job);
updateCoordinationServiceManifestNode(job);
}
} catch (CoordinationServiceException 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 {
/*
* Create the coordination service node data for the job. Note that
* getting the lock will create the node for the job (with no data)
* if it does not already exist.
* Create the coordination service manifest node data for the job.
* Note that getting the lock will create the node for the job (with
* no data) if it does not already exist.
*
* An exclusive lock is obtained before creating the node data
* 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())) {
if (null != manifestLock) {
AutoIngestJob job = new AutoIngestJob(manifest);
updateCoordinationServiceNode(job);
updateCoordinationServiceManifestNode(job);
newPendingJobsList.add(job);
}
} 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
* status was not updated.
*
* @param manifest The manifest for upgrading the node.
* @param nodeData The node data.
* @param manifest The manifest for upgrading the node.
* @param jobNodeData The auto ingest job node data.
*
* @throws InterruptedException if the thread running the input
* directory scan task is interrupted while
* blocked, i.e., if auto ingest is
* shutting down.
* @throws InterruptedException if the thread running the input
* directory scan task is interrupted
* while blocked, i.e., if auto ingest is
* 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
* 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) {
SYS_LOGGER.log(Level.SEVERE, "Attempting crash recovery for {0}", manifestPath);
try {
Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, manifest.getCaseName());
/*
* Create the recovery job.
*/
AutoIngestJob job = new AutoIngestJob(nodeData);
AutoIngestJob job = new AutoIngestJob(jobNodeData);
int numberOfCrashes = job.getNumberOfCrashes();
++numberOfCrashes;
job.setNumberOfCrashes(numberOfCrashes);
job.setCompletedDate(new Date(0));
Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, manifest.getCaseName());
if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) {
++numberOfCrashes;
job.setNumberOfCrashes(numberOfCrashes);
if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) {
job.setCompletedDate(new Date(0));
} else {
job.setCompletedDate(Date.from(Instant.now()));
}
}
if (null != caseDirectoryPath) {
job.setCaseDirectoryPath(caseDirectoryPath);
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 {
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()) {
job.setProcessingStatus(AutoIngestJob.ProcessingStatus.PENDING);
if (null != caseDirectoryPath) {
@ -1292,13 +1302,32 @@ public final class AutoIngestManager extends Observable implements PropertyChang
job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED);
if (null != caseDirectoryPath) {
try {
new AutoIngestJobLogger(manifest.getFilePath(), manifest.getDataSourceFileName(), nodeData.getCaseDirectoryPath()).logCrashRecoveryNoRetry();
new AutoIngestJobLogger(manifest.getFilePath(), manifest.getDataSourceFileName(), caseDirectoryPath).logCrashRecoveryNoRetry();
} catch (AutoIngestJobLoggerException 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 {
try {
manifestLock.release();
@ -1352,15 +1381,15 @@ public final class AutoIngestManager extends Observable implements PropertyChang
job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED);
/*
* Try to upgrade/update the coordination service node data
* for the job. It is possible that two hosts will both try
* to obtain the lock to do the upgrade operation at the
* same time. If this happens, the host that is holding the
* lock will complete the upgrade operation.
* Try to upgrade/update the coordination service manifest
* node data for the job. It is possible that two hosts will
* both try to obtain the lock to do the upgrade operation
* at the same time. If this happens, the host that is
* holding the lock will complete the upgrade operation.
*/
try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) {
if (null != manifestLock) {
updateCoordinationServiceNode(job);
updateCoordinationServiceManifestNode(job);
}
} catch (CoordinationServiceException 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;
} else if (ex instanceof FileExportException) {
errorState = ErrorState.FILE_EXPORT_ERROR;
} else if (ex instanceof AutoIngestAlertFileException) {
errorState = ErrorState.ALERT_FILE_ERROR;
} else if (ex instanceof AutoIngestJobLoggerException) {
errorState = ErrorState.JOB_LOGGER_ERROR;
} else if (ex instanceof AutoIngestDataSourceProcessorException) {
@ -1691,9 +1718,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* @throws FileExportException if there is an
* error exporting
* files.
* @throws AutoIngestAlertFileException if there is an
* error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an
* error writing to
* the auto ingest
@ -1710,7 +1734,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* auto ingest node
* 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");
Lock manifestLock = JobProcessingTask.this.dequeueAndLockNextJob();
while (null != manifestLock) {
@ -1890,9 +1914,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* @throws FileExportException if there is an
* error exporting
* files.
* @throws AutoIngestAlertFileException if there is an
* error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an
* error writing to
* the auto ingest
@ -1909,13 +1930,13 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* auto ingest node
* 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();
SYS_LOGGER.log(Level.INFO, "Started processing of {0}", manifestPath);
currentJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.PROCESSING);
currentJob.setProcessingStage(AutoIngestJob.Stage.STARTING, Date.from(Instant.now()));
currentJob.setProcessingHostName(AutoIngestManager.LOCAL_HOST_NAME);
updateCoordinationServiceNode(currentJob);
updateCoordinationServiceManifestNode(currentJob);
setChanged();
notifyObservers(Event.JOB_STARTED);
eventPublisher.publishRemotely(new AutoIngestJobStartedEvent(currentJob));
@ -1939,14 +1960,14 @@ public final class AutoIngestManager extends Observable implements PropertyChang
currentJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.PENDING);
}
currentJob.setProcessingHostName("");
updateCoordinationServiceNode(currentJob);
updateCoordinationServiceManifestNode(currentJob);
boolean retry = (!currentJob.isCanceled() && !currentJob.isCompleted());
SYS_LOGGER.log(Level.INFO, "Completed processing of {0}, retry = {1}", new Object[]{manifestPath, retry});
if (currentJob.isCanceled()) {
Path caseDirectoryPath = currentJob.getCaseDirectoryPath();
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);
jobLogger.logJobCancelled();
}
@ -1994,7 +2015,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* i.e., if auto ingest is
* 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();
if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) {
return;
@ -2115,7 +2136,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
Case.openAsCurrentCase(metadataFilePath.toString());
} else {
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
* that the new case folder is visible on the
@ -2158,8 +2180,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* level ingest modules.
* @throws FileExportException if there is an error exporting
* files.
* @throws AutoIngestAlertFileException if there is an error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the
* case.
@ -2168,7 +2188,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto
* 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 {
if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) {
return;
@ -2196,8 +2216,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* level ingest modules.
* @throws FileExportException if there is an error exporting
* files.
* @throws AutoIngestAlertFileException if there is an error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the
* case.
@ -2206,12 +2224,12 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto
* 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()) {
return;
}
DataSource dataSource = identifyDataSource();
AutoIngestDataSource dataSource = identifyDataSource();
if (null == dataSource) {
currentJob.setProcessingStage(AutoIngestJob.Stage.COMPLETED, Date.from(Instant.now()));
return;
@ -2254,8 +2272,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
*
* @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
* the auto ingest log for the
* case.
@ -2264,7 +2280,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* interrupted while blocked, i.e.,
* if auto ingest is shutting down.
*/
private DataSource identifyDataSource() throws AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException {
private AutoIngestDataSource identifyDataSource() throws AutoIngestJobLoggerException, InterruptedException, CaseNodeData.InvalidDataException, CoordinationServiceException {
Manifest manifest = currentJob.getManifest();
Path manifestPath = manifest.getFilePath();
SYS_LOGGER.log(Level.INFO, "Identifying data source for {0} ", manifestPath);
@ -2276,22 +2292,20 @@ public final class AutoIngestManager extends Observable implements PropertyChang
if (!dataSource.exists()) {
SYS_LOGGER.log(Level.SEVERE, "Missing data source for {0}", manifestPath);
currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logMissingDataSource();
return null;
}
String deviceId = manifest.getDeviceId();
return new DataSource(deviceId, dataSourcePath);
return new AutoIngestDataSource(deviceId, dataSourcePath);
}
/**
* Passes the data source for the current job through a data source
* processor that adds it to the case database.
*
* @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
* the auto ingest log for the
* case.
@ -2300,23 +2314,20 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto
* ingest is shutting down.
*/
private void runDataSourceProcessor(Case caseForJob, DataSource dataSource) throws InterruptedException, AutoIngestAlertFileException, AutoIngestJobLoggerException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException {
private void runDataSourceProcessor(Case caseForJob, AutoIngestDataSource dataSource) throws InterruptedException, AutoIngestJobLoggerException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, CaseNodeData.InvalidDataException, CoordinationServiceException {
Manifest manifest = currentJob.getManifest();
Path manifestPath = manifest.getFilePath();
SYS_LOGGER.log(Level.INFO, "Adding data source for {0} ", manifestPath);
currentJob.setProcessingStage(AutoIngestJob.Stage.ADDING_DATA_SOURCE, Date.from(Instant.now()));
UUID taskId = UUID.randomUUID();
DataSourceProcessorCallback callBack = new AddDataSourceCallback(caseForJob, dataSource, taskId, ingestLock);
DataSourceProcessorProgressMonitor progressMonitor = new DoNothingDSPProgressMonitor();
Path caseDirectoryPath = currentJob.getCaseDirectoryPath();
AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, manifest.getDataSourceFileName(), caseDirectoryPath);
try {
caseForJob.notifyAddingDataSource(taskId);
Map<AutoIngestDataSourceProcessor, Integer> validDataSourceProcessorsMap;
// Get an ordered list of data source processors to try
List<AutoIngestDataSourceProcessor> validDataSourceProcessors;
try {
// lookup all AutomatedIngestDataSourceProcessors and poll which ones are able to process the current data source
validDataSourceProcessorsMap = DataSourceProcessorUtility.getDataSourceProcessor(dataSource.getPath());
validDataSourceProcessors = DataSourceProcessorUtility.getOrderedListOfDataSourceProcessors(dataSource.getPath());
} catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) {
SYS_LOGGER.log(Level.SEVERE, "Exception while determining best data source processor for {0}", dataSource.getPath());
// rethrow the exception. It will get caught & handled upstream and will result in AIM auto-pause.
@ -2324,24 +2335,22 @@ public final class AutoIngestManager extends Observable implements PropertyChang
}
// did we find a data source processor that can process the data source
if (validDataSourceProcessorsMap.isEmpty()) {
if (validDataSourceProcessors.isEmpty()) {
// This should never happen. We should add all unsupported data sources as logical files.
AutoIngestAlertFile.create(caseDirectoryPath);
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
currentJob.setErrorsOccurred(true);
jobLogger.logFailedToIdentifyDataSource();
SYS_LOGGER.log(Level.WARNING, "Unsupported data source {0} for {1}", new Object[]{dataSource.getPath(), manifestPath}); // NON-NLS
return;
}
// Get an ordered list of data source processors to try
List<AutoIngestDataSourceProcessor> validDataSourceProcessors = validDataSourceProcessorsMap.entrySet().stream()
.sorted(Map.Entry.<AutoIngestDataSourceProcessor, Integer>comparingByValue().reversed())
.map(Map.Entry::getKey)
.collect(Collectors.toList());
synchronized (ingestLock) {
// Try each DSP in decreasing order of confidence
for (AutoIngestDataSourceProcessor selectedProcessor : validDataSourceProcessors) {
UUID taskId = UUID.randomUUID();
caseForJob.notifyAddingDataSource(taskId);
DataSourceProcessorCallback callBack = new AddDataSourceCallback(caseForJob, dataSource, taskId, ingestLock);
caseForJob.notifyAddingDataSource(taskId);
jobLogger.logDataSourceProcessorSelected(selectedProcessor.getDataSourceType());
SYS_LOGGER.log(Level.INFO, "Identified data source type for {0} as {1}", new Object[]{manifestPath, selectedProcessor.getDataSourceType()});
try {
@ -2352,7 +2361,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
// 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.
AutoIngestAlertFile.create(caseDirectoryPath);
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
currentJob.setErrorsOccurred(true);
jobLogger.logDataSourceProcessorError(selectedProcessor.getDataSourceType());
SYS_LOGGER.log(Level.SEVERE, "Exception while processing {0} with data source processor {1}", new Object[]{dataSource.getPath(), selectedProcessor.getDataSourceType()});
@ -2376,8 +2385,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
*
* @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
* the auto ingest log for the
* case.
@ -2386,7 +2393,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto
* ingest is shutting down.
*/
private void logDataSourceProcessorResult(DataSource dataSource) throws AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException {
private void logDataSourceProcessorResult(AutoIngestDataSource dataSource) throws AutoIngestJobLoggerException, InterruptedException, CaseNodeData.InvalidDataException, CoordinationServiceException {
Manifest manifest = currentJob.getManifest();
Path manifestPath = manifest.getFilePath();
Path caseDirectoryPath = currentJob.getCaseDirectoryPath();
@ -2398,7 +2405,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
jobLogger.logDataSourceAdded();
if (dataSource.getContent().isEmpty()) {
currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logNoDataSourceContent();
}
break;
@ -2410,7 +2417,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
jobLogger.logDataSourceAdded();
if (dataSource.getContent().isEmpty()) {
currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logNoDataSourceContent();
}
break;
@ -2420,7 +2427,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});
}
currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logFailedToAddDataSource();
break;
}
@ -2434,7 +2441,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
*/
SYS_LOGGER.log(Level.WARNING, "Cancellation while waiting for data source processor for {0}", manifestPath);
currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logDataSourceProcessorCancelled();
}
}
@ -2448,8 +2455,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
*
* @throws AnalysisStartupException if there is an error analyzing
* the data source.
* @throws AutoIngestAlertFileException if there is an error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the
* case.
@ -2458,7 +2463,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto
* ingest is shutting down.
*/
private void analyze(DataSource dataSource) throws AnalysisStartupException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException {
private void analyze(AutoIngestDataSource dataSource) throws AnalysisStartupException, AutoIngestJobLoggerException, InterruptedException, CaseNodeData.InvalidDataException, CoordinationServiceException {
Manifest manifest = currentJob.getManifest();
Path manifestPath = manifest.getFilePath();
SYS_LOGGER.log(Level.INFO, "Starting ingest modules analysis for {0} ", manifestPath);
@ -2490,7 +2495,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
if (!cancelledModules.isEmpty()) {
SYS_LOGGER.log(Level.WARNING, String.format("Ingest module(s) cancelled for %s", manifestPath));
currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
for (String module : snapshot.getCancelledDataSourceIngestModules()) {
SYS_LOGGER.log(Level.WARNING, String.format("%s ingest module cancelled for %s", module, manifestPath));
jobLogger.logIngestModuleCancelled(module);
@ -2500,7 +2505,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} else {
currentJob.setProcessingStage(AutoIngestJob.Stage.CANCELLING, Date.from(Instant.now()));
currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logAnalysisCancelled();
CancellationReason cancellationReason = snapshot.getCancellationReason();
if (CancellationReason.NOT_CANCELLED != cancellationReason && CancellationReason.USER_CANCELLED != cancellationReason) {
@ -2513,13 +2518,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());
}
currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logIngestModuleStartupErrors();
throw new AnalysisStartupException(String.format("Error(s) during ingest module startup for %s", manifestPath));
} else {
SYS_LOGGER.log(Level.SEVERE, String.format("Ingest manager ingest job start error for %s", manifestPath), ingestJobStartResult.getStartupException());
currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logAnalysisStartupError();
throw new AnalysisStartupException("Ingest manager error starting job", ingestJobStartResult.getStartupException());
}
@ -2528,7 +2533,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});
}
currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logIngestJobSettingsErrors();
throw new AnalysisStartupException("Error(s) in ingest job settings");
}
@ -2547,8 +2552,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
*
* @throws FileExportException if there is an error exporting
* the files.
* @throws AutoIngestAlertFileException if there is an error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the
* case.
@ -2557,7 +2560,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto
* ingest is shutting down.
*/
private void exportFiles(DataSource dataSource) throws FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException {
private void exportFiles(AutoIngestDataSource dataSource) throws FileExportException, AutoIngestJobLoggerException, InterruptedException, CaseNodeData.InvalidDataException, CoordinationServiceException {
Manifest manifest = currentJob.getManifest();
Path manifestPath = manifest.getFilePath();
SYS_LOGGER.log(Level.INFO, "Exporting files for {0}", manifestPath);
@ -2573,11 +2576,11 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} catch (FileExportException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error doing file export for %s", manifestPath), ex);
currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logFileExportError();
}
}
/**
* A data source processor progress monitor does nothing. There is
* currently no mechanism for showing or recording data source processor
@ -2739,7 +2742,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
currentJob.getProcessingStageDetails();
setChanged();
notifyObservers(Event.JOB_STATUS_UPDATED);
updateCoordinationServiceNode(currentJob);
updateCoordinationServiceManifestNode(currentJob);
eventPublisher.publishRemotely(new AutoIngestJobStatusEvent(currentJob));
}
@ -2842,7 +2845,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
CASE_MANAGEMENT_ERROR("Case management error"),
ANALYSIS_STARTUP_ERROR("Analysis startup error"),
FILE_EXPORT_ERROR("File export error"),
ALERT_FILE_ERROR("Alert file error"),
JOB_LOGGER_ERROR("Job logger error"),
DATA_SOURCE_PROCESSOR_ERROR("Data source processor error"),
UNEXPECTED_EXCEPTION("Unknown error");
@ -2917,7 +2919,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
PARTIALLY_DELETED,
FULLY_DELETED
}
static final class AutoIngestManagerException extends Exception {
private static final long serialVersionUID = 1L;

View File

@ -0,0 +1,160 @@
/*
* 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.List;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* Collects metrics for an auto ingest cluster.
*/
final class AutoIngestMetricsCollector {
private static final Logger LOGGER = Logger.getLogger(AutoIngestMetricsCollector.class.getName());
private CoordinationService coordinationService;
/**
* Creates an instance of the AutoIngestMetricsCollector.
*
* @throws AutoIngestMetricsCollector.AutoIngestMetricsCollectorException
*/
AutoIngestMetricsCollector() throws AutoIngestMetricsCollectorException {
try {
coordinationService = CoordinationService.getInstance();
} catch (CoordinationServiceException ex) {
throw new AutoIngestMetricsCollectorException("Failed to get coordination service", ex); //NON-NLS
}
}
/**
* Gets a new metrics snapshot from the coordination service for an auto
* ingest cluster.
*
* @return The metrics snapshot.
*/
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);
AutoIngestJob.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 (CoordinationService.CoordinationServiceException ex) {
LOGGER.log(Level.SEVERE, "Failed to get node list from coordination service", ex);
return new MetricsSnapshot();
}
}
/**
* A snapshot of metrics for an auto ingest cluster.
*/
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(java.util.Date date) {
completedJobDates.add(date.getTime());
}
}
/**
* Exception type thrown when there is an error completing an auto ingest
* metrics collector operation.
*/
static final class AutoIngestMetricsCollectorException 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 metrics collector operation.
*
* @param message The exception message.
*/
private AutoIngestMetricsCollectorException(String message) {
super(message);
}
/**
* Constructs an instance of the exception type thrown when there is an
* error completing an auto ingest metrics collector operation.
*
* @param message The exception message.
* @param cause A Throwable cause for the error.
*/
private AutoIngestMetricsCollectorException(String message, Throwable cause) {
super(message, cause);
}
}
}

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,212 @@
/*
* 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;
/**
* Displays auto ingest metrics for a cluster.
*/
final class AutoIngestMetricsDialog extends javax.swing.JDialog {
private final AutoIngestMetricsCollector autoIngestMetricsCollector;
/**
* Creates an instance of AutoIngestMetricsDialog
*
* @param parent The parent container.
*/
@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) throws AutoIngestMetricsDialogException {
super((Window) parent, NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.title.text"), ModalityType.MODELESS);
try {
autoIngestMetricsCollector = new AutoIngestMetricsCollector();
} catch (AutoIngestMetricsCollector.AutoIngestMetricsCollectorException ex) {
throw new AutoIngestMetricsDialogException("Error starting up the auto ingest metrics dialog.", ex);
}
initComponents();
reportTextArea.setText(NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.initReportText"));
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;
}
AutoIngestMetricsCollector.MetricsSnapshot metricsSnapshot = autoIngestMetricsCollector.queryCoordinationServiceForMetrics();
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
));
}
/**
* Exception type thrown when there is an error completing an auto ingest
* metrics dialog operation.
*/
static final class AutoIngestMetricsDialogException 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 metrics dialog operation.
*
* @param message The exception message.
*/
private AutoIngestMetricsDialogException(String message) {
super(message);
}
/**
* Constructs an instance of the exception type thrown when there is an
* error completing an auto ingest metrics dialog operation.
*
* @param message The exception message.
* @param cause A Throwable cause for the error.
*/
private AutoIngestMetricsDialogException(String message, Throwable cause) {
super(message, cause);
}
}
/**
* 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

@ -43,7 +43,7 @@ import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJob.ProcessingSta
* An auto ingest monitor responsible for monitoring and reporting the
* 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 int NUM_COORD_SVC_QUERY_THREADS = 1;
@ -265,11 +265,15 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang
}
} catch (InterruptedException 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);
} catch (AutoIngestJob.AutoIngestJobException ex) {
LOGGER.log(Level.SEVERE, String.format("Failed to create a job for '%s'", node), ex);
}
}
return newJobsSnapshot;
} catch (CoordinationServiceException ex) {
LOGGER.log(Level.SEVERE, "Failed to get node list from coordination service", ex);
return new JobsSnapshot();
@ -552,4 +556,4 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang
}
}
}
}

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.lbRunning.text=Running 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.
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.
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.cannotFindLog=Unable to find the selected case log file
DisplayLogDialog.unableToShowLogFile=Unable to show log file
DisplayLogDialog.okay=Okay
ReviewModeCasePanel.bnShowLog.text=&Show Log
CopyFilesPanel.lbFrom.text=From Source
CopyFilesPanel.lbTo.text=Destination Case
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.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_Keywords_Case_Import=Case Import Settings
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.AbortingBatch=Aborting batch processing of
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
AutoIngestDashboard.lbServicesStatus.text=Services Status:
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.DeleteTooltip_1=Delete the selected 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.text=&Refresh
AutoIngestDashboard.jButton1.text=jButton1
@ -247,6 +226,11 @@ AutoIngestDashboard.prioritizeJobButton.toolTipText=Move the selected job to the
AutoIngestDashboard.prioritizeJobButton.text=Prioritize &Job
AutoIngestDashboard.prioritizeCaseButton.toolTipText=Move all images associated with a case to top of Pending queue.
AutoIngestDashboard.prioritizeCaseButton.text=Prioritize &Case
AutoIngestMetricsDialog.reportTextArea.text=
AutoIngestDashboard.clusterMetricsButton.text=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.browseButton.text=Browse
ArchiveFilePanel.pathTextField.text=

View File

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

View File

@ -21,7 +21,9 @@ package org.sleuthkit.autopsy.experimental.autoingest;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.openide.util.Lookup;
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException;
@ -30,8 +32,8 @@ import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.
* A utility class to find Data Source Processors
*/
class DataSourceProcessorUtility {
private DataSourceProcessorUtility() {
private DataSourceProcessorUtility() {
}
/**
@ -45,11 +47,7 @@ class DataSourceProcessorUtility {
* @throws
* org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
*/
static Map<AutoIngestDataSourceProcessor, Integer> getDataSourceProcessor(Path dataSourcePath) throws AutoIngestDataSourceProcessorException {
// lookup all AutomatedIngestDataSourceProcessors
Collection<? extends AutoIngestDataSourceProcessor> processorCandidates = Lookup.getDefault().lookupAll(AutoIngestDataSourceProcessor.class);
static Map<AutoIngestDataSourceProcessor, Integer> getDataSourceProcessorForFile(Path dataSourcePath, Collection<? extends AutoIngestDataSourceProcessor> processorCandidates) throws AutoIngestDataSourceProcessorException {
Map<AutoIngestDataSourceProcessor, Integer> validDataSourceProcessorsMap = new HashMap<>();
for (AutoIngestDataSourceProcessor processor : processorCandidates) {
int confidence = processor.canProcess(dataSourcePath);
@ -60,4 +58,64 @@ class DataSourceProcessorUtility {
return validDataSourceProcessorsMap;
}
/**
* A utility method to find all Data Source Processors (DSP) that are able
* to process the input data source. Only the DSPs that implement
* AutoIngestDataSourceProcessor interface are used. Returns ordered list of
* data source processors. DSPs are ordered in descending order from highest
* confidence to lowest.
*
* @param dataSourcePath Full path to the data source
*
* @return Ordered list of data source processors. DSPs are ordered in
* descending order from highest confidence to lowest.
*
* @throws
* org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
*/
static List<AutoIngestDataSourceProcessor> getOrderedListOfDataSourceProcessors(Path dataSourcePath) throws AutoIngestDataSourceProcessorException {
// lookup all AutomatedIngestDataSourceProcessors
Collection<? extends AutoIngestDataSourceProcessor> processorCandidates = Lookup.getDefault().lookupAll(AutoIngestDataSourceProcessor.class);
return getOrderedListOfDataSourceProcessors(dataSourcePath, processorCandidates);
}
/**
* A utility method to find all Data Source Processors (DSP) that are able
* to process the input data source. Only the DSPs that implement
* AutoIngestDataSourceProcessor interface are used. Returns ordered list of
* data source processors. DSPs are ordered in descending order from highest
* confidence to lowest.
*
* @param dataSourcePath Full path to the data source
* @param processorCandidates Collection of AutoIngestDataSourceProcessor objects to use
*
* @return Ordered list of data source processors. DSPs are ordered in
* descending order from highest confidence to lowest.
*
* @throws
* org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
*/
static List<AutoIngestDataSourceProcessor> getOrderedListOfDataSourceProcessors(Path dataSourcePath, Collection<? extends AutoIngestDataSourceProcessor> processorCandidates) throws AutoIngestDataSourceProcessorException {
Map<AutoIngestDataSourceProcessor, Integer> validDataSourceProcessorsMap = getDataSourceProcessorForFile(dataSourcePath, processorCandidates);
return orderDataSourceProcessorsByConfidence(validDataSourceProcessorsMap);
}
/**
* A utility method to get an ordered list of data source processors. DSPs
* are ordered in descending order from highest confidence to lowest.
*
* @param validDataSourceProcessorsMap Hash map of all DSPs that can process
* the data source along with their confidence score
* @return Ordered list of data source processors
*/
static List<AutoIngestDataSourceProcessor> orderDataSourceProcessorsByConfidence(Map<AutoIngestDataSourceProcessor, Integer> validDataSourceProcessorsMap) {
List<AutoIngestDataSourceProcessor> validDataSourceProcessors = validDataSourceProcessorsMap.entrySet().stream()
.sorted(Map.Entry.<AutoIngestDataSourceProcessor, Integer>comparingByValue().reversed())
.map(Map.Entry::getKey)
.collect(Collectors.toList());
return validDataSourceProcessors;
}
}

View File

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

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 Basis Technology Corp.
* Copyright 2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -23,27 +23,34 @@ 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;
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
* as a center-aligned icon, and grays out the cell if the table is disabled.
* A JTable cell renderer that represents whether the priority value of a job
* 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;
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
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
setHorizontalAlignment(CENTER);
if ((value instanceof Boolean)) {
if (true == (Boolean) value) {
setIcon(warningIcon);
setToolTipText(org.openide.util.NbBundle.getMessage(CaseStatusIconCellRenderer.class, "CaseStatusIconCellRenderer.tooltiptext.warning"));
if ((value instanceof Integer)) {
if ((int) value == 0) {
setIcon(null);
setToolTipText(org.openide.util.NbBundle.getMessage(PrioritizedIconCellRenderer.class, "PrioritizedIconCellRenderer.notPrioritized.tooltiptext"));
} else {
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);

View File

@ -47,6 +47,7 @@ import org.sleuthkit.autopsy.casemodule.SingleUserCaseConverter;
import org.sleuthkit.autopsy.casemodule.SingleUserCaseConverter.ImportCaseData;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import org.sleuthkit.autopsy.coreutils.TimeStampUtils;
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">
<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
=========================================================== -->
@ -23,19 +9,12 @@
<folder name="Help">
<file name="org-sleuthkit-autopsy-corecomponents-CustomAboutAction.shadow_hidden"/>
</folder>
<folder name="Case">
<file name="org-sleuthkit-autopsy-casemodule-CaseOpenAction.shadow_hidden"/>
<file name="org-sleuthkit-autopsy-experimental-autoingest-AutoIngestCaseOpenAction.shadow">
<attr name="originalFile" stringvalue="Actions/Case/org-sleuthkit-autopsy-experimental-autoingest-AutoIngestCaseOpenAction.instance"/>
<attr name="position" intvalue="101"/>
</file>
</folder>
</folder>
<folder name="Windows2">
<folder name="Windows2">
<folder name="Modes">
<file name="dashboard.wsmode" url="dashboardWsmode.xml"/>
</folder>
</folder>
</folder>
</filesystem>

View File

@ -1,10 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<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>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
@ -56,18 +52,71 @@
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" 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 type="102" alignment="0" 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"/>
</Group>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="jPanelNodeType" max="32767" attributes="0"/>
<Component id="jPanelSharedConfig" alignment="0" max="32767" attributes="0"/>
<Component id="jPanelIngestSettings" alignment="0" max="32767" 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" 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>
<EmptySpace max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -79,542 +128,65 @@
<Component id="cbJoinAutoIngestCluster" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="tbOops" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
<Component id="jPanelNodeType" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" 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"/>
<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"/>
<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>
</DimensionLayout>
</Layout>
<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">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
@ -649,6 +221,238 @@
</Property>
</Properties>
</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>
</Container>
</SubComponents>

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.experimental.configuration;
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.io.File;
import java.nio.file.Files;
import java.util.List;
@ -56,7 +57,7 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
enum OptionsUiMode {
STANDALONE, AIM, REVIEW, DOWNLOADING_CONFIGURATION
STANDALONE, AIM, DOWNLOADING_CONFIGURATION
};
/**
@ -127,21 +128,10 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
if (inStartup) {
UserPreferences.SelectedMode storedMode = UserPreferences.getMode();
inputPathTextField.requestFocusInWindow();
if (null != storedMode) {
switch (storedMode) {
case REVIEW:
jRadioButtonReview.setSelected(true);
enableOptionsBasedOnMode(OptionsUiMode.REVIEW);
break;
case AUTOINGEST:
jRadioButtonAutomated.setSelected(true);
enableOptionsBasedOnMode(OptionsUiMode.AIM);
break;
default:
cbJoinAutoIngestCluster.setSelected(false);
enableOptionsBasedOnMode(OptionsUiMode.STANDALONE);
break;
}
if (storedMode == UserPreferences.SelectedMode.AUTOINGEST) {
enableOptionsBasedOnMode(OptionsUiMode.AIM);
} else if (storedMode != null) {
enableOptionsBasedOnMode(OptionsUiMode.STANDALONE);
}
}
@ -207,22 +197,12 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
* Save mode to persistent storage.
*/
void store() {
boolean needsRestart = false;
UserPreferences.SelectedMode storedMode = UserPreferences.getMode();
boolean needsRestart = (cbJoinAutoIngestCluster.isSelected() != AutoIngestUserPreferences.getJoinAutoModeCluster());
AutoIngestUserPreferences.setJoinAutoModeCluster(cbJoinAutoIngestCluster.isSelected());
if (!cbJoinAutoIngestCluster.isSelected()) {
if(storedMode == UserPreferences.SelectedMode.AUTOINGEST) {
needsRestart = true;
}
UserPreferences.setMode(UserPreferences.SelectedMode.STANDALONE);
}
else if (jRadioButtonAutomated.isSelected()) {
if (storedMode == UserPreferences.SelectedMode.REVIEW) {
needsRestart = true;
}
} else {
UserPreferences.setMode(UserPreferences.SelectedMode.AUTOINGEST);
String imageFolderPath = getNormalizedFolderPath(inputPathTextField.getText().trim());
AutoIngestUserPreferences.setAutoModeImageFolder(imageFolderPath);
@ -234,15 +214,8 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
AutoIngestUserPreferences.setSharedConfigFolder(globalSettingsPath);
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) {
SwingUtilities.invokeLater(() -> {
JOptionPane.showMessageDialog(null,
@ -306,23 +279,14 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
configButtonErrorTextField.setText("Shared configuration folder is invalid");
}
break;
case REVIEW:
jLabelInvalidImageFolder.setVisible(false);
if (!validateResultsPath()) {
isValidNodePanel = false;
}
break;
case STANDALONE:
break;
default:
break;
}
if (jRadioButtonAutomated.isSelected()) {
if (sharedConfigCheckbox.isEnabled() && sharedConfigCheckbox.isSelected() && !validSharedConfigSettings()) {
isValidNodePanel = false;
}
if (sharedConfigCheckbox.isEnabled() && sharedConfigCheckbox.isSelected() && !validSharedConfigSettings()) {
isValidNodePanel = false;
}
return isValidNodePanel;
}
@ -550,7 +514,8 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
}
private void displayIngestJobSettingsPanel() {
this.getParent().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
IngestJobSettings ingestJobSettings = new IngestJobSettings(AutoIngestUserPreferences.getAutoModeIngestModuleContextString());
showWarnings(ingestJobSettings);
IngestJobSettingsPanel ingestJobSettingsPanel = new IngestJobSettingsPanel(ingestJobSettings);
@ -563,6 +528,8 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
ingestJobSettings.save();
showWarnings(ingestJobSettings);
}
this.getParent().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
private static void showWarnings(IngestJobSettings ingestJobSettings) {
@ -579,24 +546,17 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
private void enableOptionsBasedOnMode(OptionsUiMode mode) {
if (mode != OptionsUiMode.DOWNLOADING_CONFIGURATION) {
boolean nonMasterSharedConfig = !masterNodeCheckBox.isSelected() && sharedConfigCheckbox.isSelected();
jRadioButtonAutomated.setEnabled(cbJoinAutoIngestCluster.isSelected());
jRadioButtonReview.setEnabled(cbJoinAutoIngestCluster.isSelected());
jLabelSelectInputFolder.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
inputPathTextField.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
browseInputFolderButton.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
jLabelSelectOutputFolder.setEnabled((mode == OptionsUiMode.AIM && !nonMasterSharedConfig) || mode == OptionsUiMode.REVIEW);
outputPathTextField.setEnabled((mode == OptionsUiMode.AIM && !nonMasterSharedConfig) || mode == OptionsUiMode.REVIEW);
browseOutputFolderButton.setEnabled((mode == OptionsUiMode.AIM && !nonMasterSharedConfig) || mode == OptionsUiMode.REVIEW);
jLabelSelectOutputFolder.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
outputPathTextField.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
browseOutputFolderButton.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
jPanelSharedConfig.setEnabled(mode == OptionsUiMode.AIM);
jPanelIngestSettings.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
bnEditIngestSettings.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
bnAdvancedSettings.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
bnLogging.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
jPanelSharedConfig.setEnabled(mode == OptionsUiMode.AIM);
sharedConfigCheckbox.setEnabled(mode == OptionsUiMode.AIM);
masterNodeCheckBox.setEnabled(mode == OptionsUiMode.AIM && sharedConfigCheckbox.isSelected());
bnFileExport.setEnabled(mode == OptionsUiMode.AIM);
@ -613,14 +573,8 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
private OptionsUiMode getModeFromRadioButtons() {
if (!cbJoinAutoIngestCluster.isSelected()) {
return OptionsUiMode.STANDALONE;
}
if (jRadioButtonAutomated.isSelected()) {
return OptionsUiMode.AIM;
} else if (jRadioButtonReview.isSelected()) {
return OptionsUiMode.REVIEW;
} 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
private void initComponents() {
modeRadioButtons = new javax.swing.ButtonGroup();
nodeScrollPane = new javax.swing.JScrollPane();
nodePanel = new javax.swing.JPanel();
jPanelNodeType = new javax.swing.JPanel();
jLabelSelectMode = new javax.swing.JLabel();
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();
cbJoinAutoIngestCluster = new javax.swing.JCheckBox();
tbOops = new javax.swing.JTextField();
bnEditIngestSettings = new javax.swing.JButton();
bnAdvancedSettings = new javax.swing.JButton();
bnFileExport = new javax.swing.JButton();
bnLogging = new javax.swing.JButton();
cbJoinAutoIngestCluster = new javax.swing.JCheckBox();
tbOops = new javax.swing.JTextField();
browseOutputFolderButton = new javax.swing.JButton();
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));
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
jPanelNodeType.setMinimumSize(new java.awt.Dimension(50, 50));
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() {
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) {
jRadioButtonAutomatedActionPerformed(evt);
cbJoinAutoIngestClusterActionPerformed(evt);
}
});
modeRadioButtons.add(jRadioButtonReview);
org.openide.awt.Mnemonics.setLocalizedText(jRadioButtonReview, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jRadioButtonReview.text")); // NOI18N
jRadioButtonReview.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jRadioButtonReview.toolTipText")); // NOI18N
jRadioButtonReview.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
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
tbOops.setEditable(false);
tbOops.setFont(tbOops.getFont().deriveFont(tbOops.getFont().getStyle() | java.awt.Font.BOLD, 12));
tbOops.setForeground(new java.awt.Color(255, 0, 0));
tbOops.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.tbOops.text")); // NOI18N
tbOops.setBorder(null);
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
@ -949,46 +662,94 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
}
});
javax.swing.GroupLayout jPanelIngestSettingsLayout = new javax.swing.GroupLayout(jPanelIngestSettings);
jPanelIngestSettings.setLayout(jPanelIngestSettingsLayout);
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() {
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) {
cbJoinAutoIngestClusterActionPerformed(evt);
browseOutputFolderButtonActionPerformed(evt);
}
});
tbOops.setEditable(false);
tbOops.setFont(tbOops.getFont().deriveFont(tbOops.getFont().getStyle() | java.awt.Font.BOLD, 12));
tbOops.setForeground(new java.awt.Color(255, 0, 0));
tbOops.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.tbOops.text")); // NOI18N
tbOops.setBorder(null);
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);
}
});
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);
nodePanel.setLayout(nodePanelLayout);
@ -998,14 +759,56 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
.addContainerGap()
.addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.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)
.addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, 465, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(jPanelNodeType, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jPanelSharedConfig, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jPanelIngestSettings, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addComponent(jLabelInvalidImageFolder, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(nodePanelLayout.createSequentialGroup()
.addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(uploadButton, javax.swing.GroupLayout.PREFERRED_SIZE, 143, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(pbTaskInProgress, javax.swing.GroupLayout.PREFERRED_SIZE, 695, javax.swing.GroupLayout.PREFERRED_SIZE)
.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.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)
.addComponent(cbJoinAutoIngestCluster)
.addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(3, 3, 3)
.addComponent(jPanelNodeType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.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)
.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)
.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);
@ -1039,31 +881,35 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
);
}// </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) {
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
// First save the shared config folder and solr settings to the properties
String globalSettingsPath = getNormalizedFolderPath(sharedSettingsTextField.getText().trim());
@ -1100,31 +946,6 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
}
}//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
// Enable the global settings text box and browse button iff the checkbox is checked and enabled
setEnabledStateForSharedConfiguration();
@ -1137,10 +958,31 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
}
}//GEN-LAST:event_masterNodeCheckBoxItemStateChanged
private void cbJoinAutoIngestClusterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbJoinAutoIngestClusterActionPerformed
enableOptionsBasedOnMode(getModeFromRadioButtons());
controller.changed();
}//GEN-LAST:event_cbJoinAutoIngestClusterActionPerformed
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
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
String oldText = outputPathTextField.getText().trim();
@ -1182,24 +1024,6 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
}
}//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
JDialog jDialog = new 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
AdvancedAutoIngestSettingsPanel advancedAutoIngestSettingsPanel = new AdvancedAutoIngestSettingsPanel(getModeFromRadioButtons());
if (JOptionPane.showConfirmDialog(null, advancedAutoIngestSettingsPanel,
NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.AdvancedAutoIngestSettingsPanel.Title"),
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE) == JOptionPane.OK_OPTION) {
advancedAutoIngestSettingsPanel.store();
NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.AdvancedAutoIngestSettingsPanel.Title"),
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE) == JOptionPane.OK_OPTION) {
advancedAutoIngestSettingsPanel.store();
}
}//GEN-LAST:event_bnAdvancedSettingsActionPerformed
@ -1349,7 +1173,7 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
}
void setEnabledStateForSharedConfiguration() {
if (jRadioButtonAutomated.isSelected() && cbJoinAutoIngestCluster.isSelected()) {
if (cbJoinAutoIngestCluster.isSelected()) {
enableOptionsBasedOnMode(OptionsUiMode.AIM);
}
}
@ -1361,19 +1185,13 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
bnLogging.setEnabled(enabled);
browseInputFolderButton.setEnabled(enabled);
browseOutputFolderButton.setEnabled(enabled);
browseSharedSettingsButton.setEnabled(sharedConfigCheckbox.isSelected() && jRadioButtonAutomated.isSelected());
browseSharedSettingsButton.setEnabled(sharedConfigCheckbox.isSelected() && cbJoinAutoIngestCluster.isSelected());
configButtonErrorTextField.setEnabled(enabled);
inputPathTextField.setEnabled(enabled);
jLabelInvalidImageFolder.setEnabled(enabled);
jLabelInvalidResultsFolder.setEnabled(enabled);
jLabelSelectInputFolder.setEnabled(enabled);
jLabelSelectMode.setEnabled(enabled);
jLabelSelectOutputFolder.setEnabled(enabled);
jPanelIngestSettings.setEnabled(enabled);
jPanelNodeType.setEnabled(enabled);
jPanelSharedConfig.setEnabled(enabled);
jRadioButtonAutomated.setEnabled(enabled);
jRadioButtonReview.setEnabled(enabled);
outputPathTextField.setEnabled(enabled);
}
@ -1389,22 +1207,13 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
private javax.swing.JTextField configButtonErrorTextField;
private javax.swing.JButton downloadButton;
private javax.swing.JTextField inputPathTextField;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabelCurrentTask;
private javax.swing.JLabel jLabelInvalidImageFolder;
private javax.swing.JLabel jLabelInvalidResultsFolder;
private javax.swing.JLabel jLabelSelectInputFolder;
private javax.swing.JLabel jLabelSelectMode;
private javax.swing.JLabel jLabelSelectOutputFolder;
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.ButtonGroup modeRadioButtons;
private javax.swing.JPanel nodePanel;
private javax.swing.JScrollPane nodeScrollPane;
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.
AutoIngestSettingsPanel.AdvancedAutoIngestSettingsPanel.Title=Advanced Settings
AutoIngestSettingsPanel.browseGlobalSettingsButton.text=Browse
AutoIngestSettingsPanel.browseSharedSettingsButton.text=Browse
AutoIngestSettingsPanel.CannotAccess=Cannot access
AutoIngestSettingsPanel.cbJoinAutoIngestCluster.text=Join auto ingest cluster
AutoIngestSettingsPanel.CheckPermissions=Check permissions.
AutoIngestSettingsPanel.configButtonErrorTextField.text=configButtonErrorTextField
AutoIngestSettingsPanel.downloadButton.text=Download Config
AutoIngestSettingsPanel.EmptySettingsDirectory=Enter path to settings directory
AutoIngestSettingsPanel.ErrorSettingDefaultFolder=Error creating default folder
AutoIngestSettingsPanel.FileExportRules.text=File Export Rules
@ -36,12 +33,8 @@ AutoIngestSettingsPanel.globalSettingsErrorTextField.text=
AutoIngestSettingsPanel.globalSettingsTextField.text=
AutoIngestSettingsPanel.ImageDirectoryUnspecified=Shared images folder must be set
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.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.nodePanel.TabConstraints.tabTitle=Node Configuration
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
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.uploadButton.text=Save & Upload Config
AutoIngestSettingsPanel.validationErrMsg.incomplete=Fill in all values
AutoIngestSettingsPanel.validationErrMsg.invalidDatabasePort=Invalid database 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.numberOfFileIngestThreadsComboBox.toolTipText=The number of threads running file level ingest modules.
NodeStatusLogPanel.tbDbName.toolTipText_1=Database name
AutoIngestSettingsPanel.jPanelNodeType.border.title=Node Type Setup
AutoIngestSettingsPanel.jLabel1.text=
AutoIngestSettingsPanel.sharedSettingsTextField.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.jLabelInvalidImageFolder.text=jLabelInvalidImageFolder
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.text=
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.bnFileExport.text=File Export 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 (localDb.exists()) {
List<HashDbManager.HashDb> hashDbs = HashDbManager.getInstance().getAllFileTypeHashSets();
List<HashDbManager.HashDb> hashDbs = HashDbManager.getInstance().getAllHashSets();
HashDbManager.HashDb matchingDb = null;
for (HashDbManager.HashDb db : hashDbs) {
try {
@ -1122,7 +1122,7 @@ public class SharedConfiguration {
try {
HashDbManager hashDbManager = HashDbManager.getInstance();
hashDbManager.loadLastSavedConfiguration();
for (HashDb hashDb : hashDbManager.getAllFileTypeHashSets()) {
for (HashDbManager.HashDb hashDb : hashDbManager.getAllHashSets()) {
if (hashDb.hasIndexOnly()) {
results.add(hashDb.getIndexPath());
} else {

View File

@ -139,8 +139,31 @@ final class GlobalListSettingsPanel extends javax.swing.JPanel implements Option
@Override
public void addPropertyChangeListener(PropertyChangeListener 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

View File

@ -205,7 +205,13 @@ class HighlightedText implements IndexedText {
*/
synchronized private void loadPageInfoFromHits() {
isLiteral = hits.getQuery().isLiteral();
//organize the hits by page, filter as needed
/**
* Organize the hits by page, filter as needed.
* We process *every* keyword here because in the case of a regular
* expression search there may be multiple different keyword
* hits located in different chunks for the same file/artifact.
*/
for (Keyword k : hits.getKeywords()) {
for (KeywordHit hit : hits.getResults(k)) {
int chunkID = hit.getChunkId();

View File

@ -38,12 +38,9 @@ class KeywordHit implements Comparable<KeywordHit> {
private static final String GET_CONTENT_ID_FROM_ARTIFACT_ID = "SELECT obj_id FROM blackboard_artifacts WHERE artifact_id = ";
private final String solrDocumentId;
private final long solrObjectId;
private final int chunkId;
private final String snippet;
private final long contentID;
private final boolean hitOnArtifact;
private final String hit;
/**
@ -56,14 +53,10 @@ class KeywordHit implements Comparable<KeywordHit> {
* For some searches (ie substring, regex) this will be
* different than the search term.
*
* @throws TskCoreException If there is a problem getting the underlying
* content associated with a hit on the text of an
* artifact.
*/
KeywordHit(String solrDocumentId, String snippet, String hit) throws TskCoreException {
KeywordHit(String solrDocumentId, String snippet, String hit) {
this.snippet = StringUtils.stripToEmpty(snippet);
this.hit = hit;
this.solrDocumentId = solrDocumentId;
/*
* Parse the Solr document id to get the Solr object id and chunk id.
@ -83,28 +76,6 @@ class KeywordHit implements Comparable<KeywordHit> {
this.solrObjectId = Long.parseLong(split[0]);
this.chunkId = Integer.parseInt(split[1]);
}
//artifacts have negative obj ids
hitOnArtifact = this.solrObjectId < 0;
if (hitOnArtifact) {
// If the hit was in an artifact, look up the source content for the artifact.
SleuthkitCase caseDb = Case.getCurrentCase().getSleuthkitCase();
try (SleuthkitCase.CaseDbQuery executeQuery =
caseDb.executeQuery(GET_CONTENT_ID_FROM_ARTIFACT_ID + this.solrObjectId);
ResultSet resultSet = executeQuery.getResultSet();) {
if (resultSet.next()) {
contentID = resultSet.getLong("obj_id");
} else {
throw new TskCoreException("Failed to get obj_id for artifact with artifact_id =" + this.solrObjectId + ". No matching artifact was found.");
}
} catch (SQLException ex) {
throw new TskCoreException("Error getting obj_id for artifact with artifact_id =" + this.solrObjectId, ex);
}
} else {
//else the object id is for content.
contentID = this.solrObjectId;
}
}
String getHit() {
@ -112,7 +83,7 @@ class KeywordHit implements Comparable<KeywordHit> {
}
String getSolrDocumentId() {
return this.solrDocumentId;
return Long.toString(solrObjectId) + Server.CHUNK_ID_SEPARATOR + Long.toString(chunkId);
}
long getSolrObjectId() {
@ -131,8 +102,36 @@ class KeywordHit implements Comparable<KeywordHit> {
return this.snippet;
}
long getContentID() {
return this.contentID;
/**
* Get the content id associated with the content underlying hit.
* For hits on files this will be the same as the object id associated
* with the file. For hits on artifacts we look up the id of the object
* that produced the artifact.
*
* @return The id of the underlying content associated with the hit.
* @throws TskCoreException If there is a problem getting the underlying
* content associated with a hit on the text of an
* artifact.
*/
long getContentID() throws TskCoreException {
if (isArtifactHit()) {
// If the hit was in an artifact, look up the source content for the artifact.
SleuthkitCase caseDb = Case.getCurrentCase().getSleuthkitCase();
try (SleuthkitCase.CaseDbQuery executeQuery =
caseDb.executeQuery(GET_CONTENT_ID_FROM_ARTIFACT_ID + this.solrObjectId);
ResultSet resultSet = executeQuery.getResultSet();) {
if (resultSet.next()) {
return resultSet.getLong("obj_id");
} else {
throw new TskCoreException("Failed to get obj_id for artifact with artifact_id =" + this.solrObjectId + ". No matching artifact was found.");
}
} catch (SQLException ex) {
throw new TskCoreException("Error getting obj_id for artifact with artifact_id =" + this.solrObjectId, ex);
}
} else {
//else the object id is for content.
return this.solrObjectId;
}
}
/**
@ -141,7 +140,8 @@ class KeywordHit implements Comparable<KeywordHit> {
* @return
*/
boolean isArtifactHit() {
return hitOnArtifact;
// artifacts have negative obj ids
return this.solrObjectId < 0;
}
/**
@ -150,7 +150,7 @@ class KeywordHit implements Comparable<KeywordHit> {
* @return The artifact whose indexed text this hit is in.
*/
Optional<Long> getArtifactID() {
if (hitOnArtifact) {
if (isArtifactHit()) {
return Optional.of(solrObjectId);
} else {
return Optional.empty();

View File

@ -52,9 +52,34 @@ final class KeywordSearchGlobalSettingsPanel extends IngestModuleGlobalSettingsP
@Override
public void addPropertyChangeListener(PropertyChangeListener l) {
super.addPropertyChangeListener(l);
listsPanel.addPropertyChangeListener(l);
languagesPanel.addPropertyChangeListener(l);
generalPanel.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 != listsPanel) {
listsPanel.addPropertyChangeListener(l);
}
if (null != languagesPanel) {
languagesPanel.addPropertyChangeListener(l);
}
if (null != generalPanel) {
generalPanel.addPropertyChangeListener(l);
}
}
@Override

Some files were not shown because too many files have changed in this diff Show More