From bf3e68fc53dfe31fb5e2c6055c6c573e1ed7a1de Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 18 Oct 2017 16:06:30 -0400 Subject: [PATCH 01/69] Removed examiner mode. --- .../AutoIngestCasePanelInterface.java | 29 -- .../autopsy/casemodule/Bundle.properties | 32 +- .../autopsy/casemodule/Bundle_ja.properties | 9 +- .../autopsy/casemodule/CaseOpenAction.java | 2 +- .../casemodule/CaseOpenMultiUserAction.java | 124 ++++++ .../autopsy/casemodule/CueBannerPanel.form | 20 +- .../autopsy/casemodule/CueBannerPanel.java | 89 ++--- .../autopsy/casemodule/MultiUserCase.java | 53 ++- .../casemodule/MultiUserCaseManager.java | 132 +++++++ .../casemodule/MultiUserCasePanel.form | 20 +- .../casemodule/MultiUserCasePanel.java | 359 ++++++------------ .../actions/EamEditCaseInfoAction.java | 2 +- Core/src/org/sleuthkit/autopsy/core/layer.xml | 8 +- .../CaseStatusIconCellRenderer.java | 11 +- .../coreutils}/GrayableCellRenderer.java | 8 +- .../coreutils}/LongDateCellRenderer.java | 6 +- .../autopsy/coreutils}/TimeStampUtils.java | 2 +- .../autoingest/AutoIngestCaseManager.java | 162 -------- .../autoingest/AutoIngestCaseOpenAction.java | 21 +- .../autoingest/AutoIngestControlPanel.java | 2 + .../autoingest/AutoIngestDashboard.java | 2 + .../AutoIngestDashboardOpenAction.java | 3 +- .../experimental/autoingest/Bundle.properties | 22 +- .../CenteredGrayableCellRenderer.java | 1 + .../autoingest/DurationCellRenderer.java | 24 ++ .../experimental/autoingest/PathUtils.java | 1 + .../autoingest/ShortDateCellRenderer.java | 24 ++ .../autoingest/SingleUserCaseImporter.java | 1 + .../configuration/Bundle.properties | 29 +- 29 files changed, 594 insertions(+), 604 deletions(-) delete mode 100755 Core/src/org/sleuthkit/autopsy/casemodule/AutoIngestCasePanelInterface.java create mode 100755 Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java rename Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCase.java => Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java (74%) create mode 100755 Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java rename Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.form => Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.form (84%) rename Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java => Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.java (67%) rename {Experimental/src/org/sleuthkit/autopsy/experimental/autoingest => Core/src/org/sleuthkit/autopsy/coreutils}/CaseStatusIconCellRenderer.java (82%) rename {Experimental/src/org/sleuthkit/autopsy/experimental/autoingest => Core/src/org/sleuthkit/autopsy/coreutils}/GrayableCellRenderer.java (91%) rename {Experimental/src/org/sleuthkit/autopsy/experimental/autoingest => Core/src/org/sleuthkit/autopsy/coreutils}/LongDateCellRenderer.java (91%) rename {Experimental/src/org/sleuthkit/autopsy/experimental/autoingest => Core/src/org/sleuthkit/autopsy/coreutils}/TimeStampUtils.java (98%) delete mode 100755 Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseManager.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AutoIngestCasePanelInterface.java b/Core/src/org/sleuthkit/autopsy/casemodule/AutoIngestCasePanelInterface.java deleted file mode 100755 index 795b636b35..0000000000 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AutoIngestCasePanelInterface.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011-2017 Basis Technology Corp. - * Contact: carrier sleuthkit 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); -} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index 1fc2209750..6ce0c76f3d 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -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 @@ -219,11 +219,31 @@ CasePropertiesPanel.lbDbType.text=Case Type: CasePropertiesPanel.examinerLabel.text=Examiner: 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 +MultiUserCasePanel.rbDays.text=Days +MultiUserCasePanel.rbWeeks.text=Weeks +MultiUserCasePanel.rbMonths.text=Months +MultiUserCasePanel.rbAllCases.text=Everything +MultiUserCasePanel.bnRefresh.text=&Refresh +MultiUserCasePanel.bnOpen.text=&Open +MultiUserCasePanel.bnShowLog.toolTipText=Display case log file for selected case +MultiUserCasePanel.bnShowLog.text=&Show Auto Ingest Case Log +MultiUserCasePanel.rbGroupLabel.text=Show cases accessed in the last 10: +OpenMultiUserCasePanel.jLabel1.text=Recent Cases +OpenMultiUserCasePanel.openButton.text=Open +OpenMultiUserCasePanel.cancelButton.text=Cancel diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties index fd00f725e5..3b2b380ffc 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties @@ -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 @@ -197,3 +197,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 diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java index 533cab58c5..e4ed92d897 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java @@ -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 diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java new file mode 100755 index 0000000000..aa9b0eac6a --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java @@ -0,0 +1,124 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2017 Basis Technology Corp. + * Contact: carrier sleuthkit 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.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.KeyStroke; +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.util.lookup.ServiceProvider; +import org.openide.windows.WindowManager; +import org.sleuthkit.autopsy.core.UserPreferences; +import static org.sleuthkit.autopsy.core.UserPreferences.SelectedMode.REVIEW; +import org.sleuthkit.autopsy.coreutils.NetworkUtils; + +/** + * The action associated with the Case/Open Case menu item via the layer.xml + * file, a toolbar button, and the Create New Case button of the start up window + * that allows a user to open a case. It opens an existing case. + * + * 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(); + private static final String LOCAL_HOST_NAME = NetworkUtils.getLocalHostName(); + private static final String REVIEW_MODE_TITLE = "Open Multi-User Case (" + LOCAL_HOST_NAME + ")"; + + /** + * Constructs the action associated with the Case/Open Case menu item via + * the layer.xml file, a toolbar button, and the Create New Case button of + * the start up window that allows a user to open a case. It opens an + * existing case. + * + */ + public CaseOpenMultiUserAction() { + multiUserCaseWindow = new JDialog( + WindowManager.getDefault().getMainWindow(), + REVIEW_MODE_TITLE, + Dialog.ModalityType.APPLICATION_MODAL); + multiUserCaseWindow.getRootPane().registerKeyboardAction( + e -> { + multiUserCaseWindow.setVisible(false); + }, + KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW); + multiUserCaseWindow.add(new MultiUserCasePanel()); + multiUserCaseWindow.pack(); + multiUserCaseWindow.setResizable(false); + } + + public static void closeMultiUserCasesWindow() { + if (null != multiUserCaseWindow) { + multiUserCaseWindow.setVisible(false); + } + } + + @Override + public boolean isEnabled() { + return UserPreferences.getIsMultiUserModeEnabled(); + } + + /** + * Pops up a file chooser to allow the user to select a case metadata file + * (.aut file) and attempts to open the case described by the file. + * + * @param e The action event. + */ + @Override + public void actionPerformed(ActionEvent event) { + 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 + } +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.form index 75819e41d0..0d6525db8b 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.form @@ -28,14 +28,14 @@ - + - + @@ -66,9 +66,9 @@ - + - + @@ -216,13 +216,13 @@ - + - + @@ -237,18 +237,18 @@ - + - + - + - + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java index 2d7b17458e..48e54a3f9f 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java @@ -26,12 +26,10 @@ 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; @@ -42,13 +40,13 @@ 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 + ")"; + private static final String REVIEW_MODE_TITLE = "Open Multi-User Case (" + LOCAL_HOST_NAME + ")"; /* * This is field is static for the sake of the closeOpenRecentCasesWindow * method. */ private static JDialog recentCasesWindow; - private static JDialog autoIngestCasePanelWindow; + private static JDialog multiUserCaseWindow; public static void closeOpenRecentCasesWindow() { if (null != recentCasesWindow) { @@ -56,9 +54,9 @@ public class CueBannerPanel extends javax.swing.JPanel { } } - public static void closeAutoIngestCasesWindow() { - if (null != autoIngestCasePanelWindow) { - autoIngestCasePanelWindow.setVisible(false); + public static void closeMultiUserCasesWindow() { + if (null != multiUserCaseWindow) { + multiUserCaseWindow.setVisible(false); } } @@ -93,7 +91,7 @@ public class CueBannerPanel extends javax.swing.JPanel { private void customizeComponents() { initRecentCasesWindow(); - initAutoIngestCasesWindow(); + initMultiUserCasesWindow(); } private void initRecentCasesWindow() { @@ -119,28 +117,19 @@ public class CueBannerPanel extends javax.swing.JPanel { recentCasesWindow.setResizable(false); } - private void initAutoIngestCasesWindow() { - autoIngestCasePanelWindow = new JDialog( + private void initMultiUserCasesWindow() { + multiUserCaseWindow = new JDialog( WindowManager.getDefault().getMainWindow(), REVIEW_MODE_TITLE, Dialog.ModalityType.APPLICATION_MODAL); - autoIngestCasePanelWindow.getRootPane().registerKeyboardAction( + multiUserCaseWindow.getRootPane().registerKeyboardAction( e -> { - autoIngestCasePanelWindow.setVisible(false); + multiUserCaseWindow.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); + multiUserCaseWindow.add(new MultiUserCasePanel()); + multiUserCaseWindow.pack(); + multiUserCaseWindow.setResizable(false); } private void enableComponents() { @@ -148,9 +137,9 @@ public class CueBannerPanel extends javax.swing.JPanel { 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 +161,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 +218,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 +250,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 +279,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 +305,10 @@ 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 + 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 +316,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; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCase.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java similarity index 74% rename from Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCase.java rename to Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java index ff47423030..d1a2bc65da 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCase.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java @@ -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.casemodule; import java.io.IOException; import java.nio.file.Files; @@ -28,13 +28,14 @@ import java.util.Objects; import java.util.logging.Level; import org.sleuthkit.autopsy.casemodule.CaseMetadata; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.TimeStampUtils; /** * A representation of a case created by automated ingest. */ -class AutoIngestCase implements Comparable { +class MultiUserCase implements Comparable { - private static final Logger logger = Logger.getLogger(AutoIngestCase.class.getName()); + private static final Logger logger = Logger.getLogger(MultiUserCase.class.getName()); private final Path caseDirectoryPath; private final String caseName; private final Path metadataFilePath; @@ -46,9 +47,9 @@ class AutoIngestCase implements Comparable { * * @param caseDirectoryPath The case directory path. */ - AutoIngestCase(Path caseDirectoryPath) { + MultiUserCase(Path caseDirectoryPath) { this.caseDirectoryPath = caseDirectoryPath; - caseName = PathUtils.caseNameFromCaseDirectoryPath(caseDirectoryPath); + caseName = getCaseNameFromCaseDirectoryPath(caseDirectoryPath); metadataFilePath = caseDirectoryPath.resolve(caseName + CaseMetadata.getFileExtension()); BasicFileAttributes fileAttrs = null; try { @@ -110,16 +111,32 @@ class AutoIngestCase implements Comparable { * @return See CaseStatus enum definition. */ CaseStatus getStatus() { - if (AutoIngestAlertFile.exists(caseDirectoryPath)) { + if(caseDirectoryPath.resolve("autoingest.alert").toFile().exists()) { return CaseStatus.ALERT; } else { return CaseStatus.OK; } } + /** + * Extracts the case name from a case folder path. + * + * @param caseFolderPath A case folder path. + * + * @return A case name, with the time stamp suffix removed. + */ + static String getCaseNameFromCaseDirectoryPath(Path caseFolderPath) { + String caseName = caseFolderPath.getFileName().toString(); + if (caseName.length() > TimeStampUtils.getTimeStampLength()) { + return caseName.substring(0, caseName.length() - TimeStampUtils.getTimeStampLength()); + } else { + return caseName; + } + } + /** * Indicates whether or not some other object is "equal to" this - * AutoIngestCase object. + * MultiUserCase object. * * @param other The other object. * @@ -127,17 +144,17 @@ class AutoIngestCase implements Comparable { */ @Override public boolean equals(Object other) { - if (!(other instanceof AutoIngestCase)) { + if (!(other instanceof MultiUserCase)) { return false; } if (other == this) { return true; } - return this.caseDirectoryPath.toString().equals(((AutoIngestCase) other).caseDirectoryPath.toString()); + return this.caseDirectoryPath.toString().equals(((MultiUserCase) other).caseDirectoryPath.toString()); } /** - * Returns a hash code value for this AutoIngestCase object. + * Returns a hash code value for this MultiUserCase object. * * @return The has code. */ @@ -151,31 +168,31 @@ class AutoIngestCase implements Comparable { } /** - * Compares this AutopIngestCase object with abnother AutoIngestCase object - * for order. + * Compares this AutopIngestCase object with abnother MultiUserCase object + for order. */ @Override - public int compareTo(AutoIngestCase other) { + 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 { + static class LastAccessedDateDescendingComparator implements Comparator { /** - * Compares two AutoIngestCase objects for order based on last accessed - * date (descending). + * Compares two MultiUserCase objects for order based on last accessed + date (descending). * - * @param object The first AutoIngestCase object + * @param object The first MultiUserCase 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) { + public int compare(MultiUserCase object, MultiUserCase otherObject) { return -object.getLastAccessedDate().compareTo(otherObject.getLastAccessedDate()); } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java new file mode 100755 index 0000000000..b1a0141a4f --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java @@ -0,0 +1,132 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2017 Basis Technology Corp. + * Contact: carrier sleuthkit 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.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import org.sleuthkit.autopsy.coordinationservice.CoordinationService; +import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; + +/** + * Handles locating and opening multi-user cases. + */ +final class MultiUserCaseManager { + + 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 MultiUserCaseManagerException + */ + List getCases() { + List cases = new ArrayList<>(); + List nodeList = coordinationService.getNodeList(CoordinationService.CategoryNode.CASES); + for (String node : nodeList) { + Path casePath = Paths.get(node); + File caseFolder = casePath.toFile(); + if(caseFolder.exists()) { + File[] autFiles = caseFolder.listFiles((dir, name) -> name.toLowerCase().endsWith(".aut")); + if(autFiles != null && autFiles.length > 0) { + cases.add(new MultiUserCase(casePath)); + } + } + } + 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); + } + + } +} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.form similarity index 84% rename from Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.form rename to Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.form index cb0f275809..a54439c4d3 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.form @@ -45,7 +45,7 @@ - + @@ -82,7 +82,7 @@ - + @@ -118,7 +118,7 @@ - + @@ -153,7 +153,7 @@ - + @@ -165,10 +165,10 @@ - + - + @@ -182,7 +182,7 @@ - + @@ -196,7 +196,7 @@ - + @@ -209,7 +209,7 @@ - + @@ -222,7 +222,7 @@ - + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.java similarity index 67% rename from Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java rename to Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.java index 2bcd335916..5f3365e8b1 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.java @@ -16,52 +16,35 @@ * 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.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.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 org.sleuthkit.autopsy.coreutils.CaseStatusIconCellRenderer; +import org.sleuthkit.autopsy.coreutils.GrayableCellRenderer; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.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; /** * 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 { +public class MultiUserCasePanel 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(MultiUserCasePanel.class.getName()); + private static final String LOG_FILE_NAME = "auto_ingest_log.txt"; + private static final MultiUserCase.LastAccessedDateDescendingComparator REVERSE_DATE_MODIFIED_COMPARATOR = new 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 +54,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 +62,11 @@ 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(MultiUserCasePanel.class, "ReviewModeCasePanel.CaseHeaderText"); + private static final String CREATEDTIME_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "ReviewModeCasePanel.CreatedTimeHeaderText"); + private static final String COMPLETEDTIME_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "ReviewModeCasePanel.LastAccessedTimeHeaderText"); + private static final String STATUS_ICON_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "ReviewModeCasePanel.StatusIconHeaderText"); + private static final String OUTPUT_FOLDER_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "ReviewModeCasePanel.OutputFolderHeaderText"); enum COLUMN_HEADERS { @@ -99,34 +79,6 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP private final String[] columnNames = {CASE_HEADER, CREATEDTIME_HEADER, COMPLETEDTIME_HEADER, STATUS_ICON_HEADER, OUTPUT_FOLDER_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(); - } - }); - } /** * Constructs a panel that allows a user to open cases created by automated @@ -134,11 +86,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP * * @param parent The parent dialog for this panel. */ - public AutoIngestCasePanel(JDialog parent) { - init(parent); - } - - public void init(JDialog parent) { + MultiUserCasePanel() { caseTableModel = new DefaultTableModel(columnNames, 0) { private static final long serialVersionUID = 1L; @@ -146,6 +94,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)) { @@ -203,61 +152,7 @@ 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(); + refreshCasesTable(); } /** @@ -267,11 +162,25 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP private void refreshCasesTable() { try { currentlySelectedCase = getSelectedCase(); - AutoIngestCaseManager manager = AutoIngestCaseManager.getInstance(); - List theModel = manager.getCases(); - EventQueue.invokeLater(new CaseTableRefreshTask(theModel)); + MultiUserCaseManager manager = MultiUserCaseManager.getInstance(); + List 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.getCaseName(), + autoIngestCase.getCreationDate(), + autoIngestCase.getLastAccessedDate(), + (MultiUserCase.CaseStatus.OK != autoIngestCase.getStatus()), + autoIngestCase.getCaseDirectoryPath().toString()}); + } + } + setSelectedCase(currentlySelectedCase); + setButtons(); } catch (Exception ex) { - logger.log(Level.SEVERE, "Unexpected exception in refreshCasesTable", ex); //NON-NLS + LOGGER.log(Level.SEVERE, "Unexpected exception in refreshCasesTable", ex); //NON-NLS } } @@ -320,9 +229,30 @@ 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); + } + + /** + * 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 thePath = (String) caseTableModel.getValueAt(casesTable.convertRowIndexToModel(selectedRow), COLUMN_HEADERS.OUTPUTFOLDER.ordinal()); + retValue = Paths.get(thePath, LOG_FILE_NAME); + } + + return retValue; } /** @@ -332,91 +262,44 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP */ private void openCase(Path caseMetadataFilePath) { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - new SwingWorker() { - - @Override - protected Void doInBackground() throws Exception { - AutoIngestCaseManager.getInstance().openCase(caseMetadataFilePath); - stopCasesTableRefreshes(); - StartupWindowProvider.getInstance().close(); - CueBannerPanel.closeAutoIngestCasesWindow(); - return null; + try { + StartupWindowProvider.getInstance().close(); + CueBannerPanel.closeMultiUserCasesWindow(); + CaseOpenMultiUserAction.closeMultiUserCasesWindow(); + 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()); } - - @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)); - } - } - }.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 final List cases; - - CaseTableRefreshTask(List cases) { - setButtons(); - this.cases = cases; + 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; } - - /** - * @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()}); - } - } - 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); - } - + return ((currentTime - inputTime) / (1000 * 60 * 60 * 24)) < (numberOfUnits * multiplier); } /** @@ -443,7 +326,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(MultiUserCasePanel.class, "MultiUserCasePanel.bnOpen.text")); // NOI18N bnOpen.setEnabled(false); bnOpen.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -463,7 +346,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(MultiUserCasePanel.class, "MultiUserCasePanel.bnRefresh.text")); // NOI18N bnRefresh.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { bnRefreshActionPerformed(evt); @@ -472,7 +355,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(MultiUserCasePanel.class, "MultiUserCasePanel.rbAllCases.text")); // NOI18N rbAllCases.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent evt) { rbAllCasesItemStateChanged(evt); @@ -494,8 +377,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(MultiUserCasePanel.class, "MultiUserCasePanel.bnShowLog.text")); // NOI18N + bnShowLog.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "MultiUserCasePanel.bnShowLog.toolTipText")); // NOI18N bnShowLog.setEnabled(false); bnShowLog.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -504,7 +387,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(MultiUserCasePanel.class, "MultiUserCasePanel.rbDays.text")); // NOI18N rbDays.setName(""); // NOI18N rbDays.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent evt) { @@ -513,7 +396,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(MultiUserCasePanel.class, "MultiUserCasePanel.rbWeeks.text")); // NOI18N rbWeeks.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent evt) { rbWeeksItemStateChanged(evt); @@ -521,7 +404,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(MultiUserCasePanel.class, "MultiUserCasePanel.rbMonths.text")); // NOI18N rbMonths.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent evt) { rbMonthsItemStateChanged(evt); @@ -529,7 +412,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(MultiUserCasePanel.class, "MultiUserCasePanel.rbGroupLabel.text")); // NOI18N javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); @@ -556,7 +439,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( @@ -591,7 +474,10 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP Path caseMetadataFilePath = Paths.get((String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.OUTPUTFOLDER.ordinal()), caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.CASE.ordinal()) + CaseMetadata.getFileExtension()); - openCase(caseMetadataFilePath); + + new Thread(() -> { + openCase(caseMetadataFilePath); + }).start(); }//GEN-LAST:event_bnOpenActionPerformed /** @@ -599,53 +485,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) { + refreshCasesTable(); + } - private void rbDaysItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbDaysItemStateChanged + private void rbDaysItemStateChanged(java.awt.event.ItemEvent evt) { if (rbDays.isSelected()) { - updateView(); + refreshCasesTable(); } - }//GEN-LAST:event_rbDaysItemStateChanged + } private void rbAllCasesItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbAllCasesItemStateChanged if (rbAllCases.isSelected()) { - updateView(); + refreshCasesTable(); } }//GEN-LAST:event_rbAllCasesItemStateChanged private void rbMonthsItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbMonthsItemStateChanged if (rbMonths.isSelected()) { - updateView(); + refreshCasesTable(); } }//GEN-LAST:event_rbMonthsItemStateChanged private void rbWeeksItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbWeeksItemStateChanged if (rbWeeks.isSelected()) { - updateView(); + refreshCasesTable(); } }//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(MultiUserCasePanel.class, "DisplayLogDialog.cannotFindLog"), + org.openide.util.NbBundle.getMessage(MultiUserCasePanel.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(MultiUserCasePanel.class, "DisplayLogDialog.cannotOpenLog"), + org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "DisplayLogDialog.unableToShowLogFile"), JOptionPane.PLAIN_MESSAGE); } } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/actions/EamEditCaseInfoAction.java b/Core/src/org/sleuthkit/autopsy/centralrepository/actions/EamEditCaseInfoAction.java index 4123e382ff..060ca11ae6 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/actions/EamEditCaseInfoAction.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/actions/EamEditCaseInfoAction.java @@ -42,7 +42,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; lazy = false ) @ActionReference(path = "Menu/Case", position = 650, separatorAfter = 824) -@Messages("CTL_CentralRepositoryCaseProperties=Central Repository Case Properties...") +@Messages("CTL_CentralRepositoryCaseProperties=Central Repository Case Properties") public final class EamEditCaseInfoAction extends CallableSystemAction implements ActionListener { EamEditCaseInfoAction() { diff --git a/Core/src/org/sleuthkit/autopsy/core/layer.xml b/Core/src/org/sleuthkit/autopsy/core/layer.xml index 95cfcd481e..fb5618c6e6 100755 --- a/Core/src/org/sleuthkit/autopsy/core/layer.xml +++ b/Core/src/org/sleuthkit/autopsy/core/layer.xml @@ -51,7 +51,7 @@ - + @@ -157,7 +157,7 @@ - + @@ -165,11 +165,11 @@ - + - + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CaseStatusIconCellRenderer.java b/Core/src/org/sleuthkit/autopsy/coreutils/CaseStatusIconCellRenderer.java similarity index 82% rename from Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CaseStatusIconCellRenderer.java rename to Core/src/org/sleuthkit/autopsy/coreutils/CaseStatusIconCellRenderer.java index 0010cc90ee..4d782a6f57 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CaseStatusIconCellRenderer.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/CaseStatusIconCellRenderer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015 Basis Technology Corp. + * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,24 +16,29 @@ * 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.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 an auto ingest alert file exists flag * as a center-aligned icon, and grays out the cell if the table is disabled. */ -class CaseStatusIconCellRenderer extends GrayableCellRenderer { +public class CaseStatusIconCellRenderer extends GrayableCellRenderer { 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)); + @Messages({ + "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" + }) @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { setHorizontalAlignment(CENTER); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/GrayableCellRenderer.java b/Core/src/org/sleuthkit/autopsy/coreutils/GrayableCellRenderer.java similarity index 91% rename from Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/GrayableCellRenderer.java rename to Core/src/org/sleuthkit/autopsy/coreutils/GrayableCellRenderer.java index 60d3b77ccd..479f30bee2 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/GrayableCellRenderer.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/GrayableCellRenderer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015 Basis Technology Corp. + * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit 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.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); } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/LongDateCellRenderer.java b/Core/src/org/sleuthkit/autopsy/coreutils/LongDateCellRenderer.java similarity index 91% rename from Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/LongDateCellRenderer.java rename to Core/src/org/sleuthkit/autopsy/coreutils/LongDateCellRenderer.java index cfa2cedb14..e347b2d28a 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/LongDateCellRenderer.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/LongDateCellRenderer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015 Basis Technology Corp. + * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit 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.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 diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/TimeStampUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/TimeStampUtils.java similarity index 98% rename from Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/TimeStampUtils.java rename to Core/src/org/sleuthkit/autopsy/coreutils/TimeStampUtils.java index fe53871dd5..01a72e775b 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/TimeStampUtils.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/TimeStampUtils.java @@ -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; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseManager.java deleted file mode 100755 index 8469ff2315..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseManager.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011-2017 Basis Technology Corp. - * Contact: carrier sleuthkit 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 getCases() throws AutoIngestCaseManagerException { - List cases = new ArrayList<>(); - List 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 getCasePaths() throws AutoIngestCaseManagerException { - try { - List nodeList = coordinationService.getNodeList(CoordinationService.CategoryNode.CASES); - List casePathList = new ArrayList(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); - } - - } -} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseOpenAction.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseOpenAction.java index e86a7bcf8a..265190663e 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseOpenAction.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseOpenAction.java @@ -27,9 +27,9 @@ 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.CaseOpenAction; import org.sleuthkit.autopsy.casemodule.StartupWindowProvider; import org.sleuthkit.autopsy.core.UserPreferences; @@ -46,23 +46,6 @@ final class AutoIngestCaseOpenAction extends CallableSystemAction implements Act 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. @@ -70,13 +53,13 @@ final class AutoIngestCaseOpenAction extends CallableSystemAction implements Act break; case STANDALONE: + case REVIEW: /** * 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()); } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index 891975223a..de737978cb 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -57,6 +57,8 @@ import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.core.ServicesMonitor; +import org.sleuthkit.autopsy.coreutils.CaseStatusIconCellRenderer; +import org.sleuthkit.autopsy.coreutils.LongDateCellRenderer; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.NetworkUtils; import org.sleuthkit.autopsy.coreutils.PlatformUtil; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java index 2d10dff258..5537d07236 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java @@ -41,7 +41,9 @@ import javax.swing.table.TableColumn; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.core.ServicesMonitor; +import org.sleuthkit.autopsy.coreutils.CaseStatusIconCellRenderer; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.LongDateCellRenderer; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestMonitor.JobsSnapshot; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboardOpenAction.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboardOpenAction.java index 7e1b1907af..10ff60da2a 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboardOpenAction.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboardOpenAction.java @@ -39,8 +39,7 @@ public final class AutoIngestDashboardOpenAction extends CallableSystemAction { @Override public boolean isEnabled() { - UserPreferences.SelectedMode mode = UserPreferences.getMode(); - return (mode == REVIEW); + return (UserPreferences.getIsMultiUserModeEnabled()); } @Override diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties index 422c7a56c4..fc80df5551 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties @@ -1,4 +1,4 @@ -CTL_OpenAction=Open Case... +CTL_OpenAction=Open Case AutoIngestDashboard.lbCompleted.text=Completed Jobs AutoIngestDashboard.lbRunning.text=Running Jobs AutoIngestDashboard.lbPending.text=Pending Jobs @@ -47,14 +47,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 +124,6 @@ CopyFilesPanel.cbThrottleNetwork.toolTipText=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 +159,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 +220,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 diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CenteredGrayableCellRenderer.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CenteredGrayableCellRenderer.java index b9040b674b..264d37eedd 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CenteredGrayableCellRenderer.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CenteredGrayableCellRenderer.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.experimental.autoingest; import static javax.swing.SwingConstants.CENTER; +import org.sleuthkit.autopsy.coreutils.GrayableCellRenderer; /** * A JTable cell renderer that center-aligns cell content and grays out the cell diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/DurationCellRenderer.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/DurationCellRenderer.java index 6bac0a996b..c61e363222 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/DurationCellRenderer.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/DurationCellRenderer.java @@ -18,10 +18,12 @@ */ package org.sleuthkit.autopsy.experimental.autoingest; +import java.awt.Color; import java.awt.Component; import java.time.Duration; import javax.swing.JTable; import static javax.swing.SwingConstants.CENTER; +import org.sleuthkit.autopsy.coreutils.GrayableCellRenderer; /** * A JTable cell renderer that renders a duration represented as a long as a @@ -71,4 +73,26 @@ class DurationCellRenderer extends GrayableCellRenderer { grayCellIfTableNotEnabled(table, isSelected); return this; } + + void grayCellIfTableNotEnabled(JTable table, boolean isSelected) { + if (table.isEnabled()) { + /* + * The table is enabled, make the foreground and background the + * normal selected or unselected color. + */ + if (isSelected) { + setBackground(table.getSelectionBackground()); + setForeground(table.getSelectionForeground()); + } else { + setBackground(table.getBackground()); + setForeground(table.getForeground()); + } + } else { + /* + * The table is disabled, make the foreground and background gray. + */ + setBackground(Color.lightGray); + setForeground(Color.darkGray); + } + } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PathUtils.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PathUtils.java index 18ce9709d5..a7d5675883 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PathUtils.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PathUtils.java @@ -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 { diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ShortDateCellRenderer.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ShortDateCellRenderer.java index 713d177c0a..f2670fa1b7 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ShortDateCellRenderer.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ShortDateCellRenderer.java @@ -18,10 +18,12 @@ */ package org.sleuthkit.autopsy.experimental.autoingest; +import java.awt.Color; import java.awt.Component; import java.text.SimpleDateFormat; import javax.swing.JTable; import static javax.swing.SwingConstants.CENTER; +import org.sleuthkit.autopsy.coreutils.GrayableCellRenderer; /** * A JTable cell renderer that renders a date represented as a long as a @@ -46,4 +48,26 @@ class ShortDateCellRenderer extends GrayableCellRenderer { grayCellIfTableNotEnabled(table, isSelected); return this; } + + void grayCellIfTableNotEnabled(JTable table, boolean isSelected) { + if (table.isEnabled()) { + /* + * The table is enabled, make the foreground and background the + * normal selected or unselected color. + */ + if (isSelected) { + setBackground(table.getSelectionBackground()); + setForeground(table.getSelectionForeground()); + } else { + setBackground(table.getBackground()); + setForeground(table.getForeground()); + } + } else { + /* + * The table is disabled, make the foreground and background gray. + */ + setBackground(Color.lightGray); + setForeground(Color.darkGray); + } + } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/SingleUserCaseImporter.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/SingleUserCaseImporter.java index e04399d321..3a5c45632f 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/SingleUserCaseImporter.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/SingleUserCaseImporter.java @@ -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 { diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties index 66ed50dd20..a12453e3c1 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties @@ -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 From d750ebfa24f0b864de69a1159ab707a2aaadf104 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 18 Oct 2017 16:43:10 -0400 Subject: [PATCH 02/69] Fixed merge conflicts. --- .../casemodule/MultiUserCaseManager.java | 26 +- .../AutoIngestSettingsPanel.form | 884 +++++++----------- .../AutoIngestSettingsPanel.java | 745 ++++++--------- 3 files changed, 635 insertions(+), 1020 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java index b1a0141a4f..ec3b42116d 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java @@ -67,21 +67,21 @@ final class MultiUserCaseManager { * * @return List of cases. * - * @throws MultiUserCaseManagerException + * @throws CoordinationServiceException */ - List getCases() { + List getCases() throws CoordinationServiceException { List cases = new ArrayList<>(); - List nodeList = coordinationService.getNodeList(CoordinationService.CategoryNode.CASES); - for (String node : nodeList) { - Path casePath = Paths.get(node); - File caseFolder = casePath.toFile(); - if(caseFolder.exists()) { - File[] autFiles = caseFolder.listFiles((dir, name) -> name.toLowerCase().endsWith(".aut")); - if(autFiles != null && autFiles.length > 0) { - cases.add(new MultiUserCase(casePath)); - } - } - } + List nodeList = coordinationService.getNodeList(CoordinationService.CategoryNode.CASES); + for (String node : nodeList) { + Path casePath = Paths.get(node); + File caseFolder = casePath.toFile(); + if(caseFolder.exists()) { + File[] autFiles = caseFolder.listFiles((dir, name) -> name.toLowerCase().endsWith(".aut")); + if(autFiles != null && autFiles.length > 0) { + cases.add(new MultiUserCase(casePath)); + } + } + } return cases; } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.form b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.form index 20c8c7a981..9965d1ad8f 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.form +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.form @@ -56,18 +56,71 @@ - - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -79,542 +132,65 @@ - - + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -649,6 +225,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.java index 4877ce9d60..892a27aab6 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.java @@ -56,7 +56,7 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel { enum OptionsUiMode { - STANDALONE, AIM, REVIEW, DOWNLOADING_CONFIGURATION + STANDALONE, AIM, DOWNLOADING_CONFIGURATION }; /** @@ -127,21 +127,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 +196,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 +213,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 +278,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; } @@ -579,24 +542,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 +569,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; } } @@ -636,289 +586,49 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel { 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 +659,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 +756,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 +814,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 +878,35 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel { ); }// //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 +943,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 +955,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 +1021,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 +1063,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 +1170,7 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel { } void setEnabledStateForSharedConfiguration() { - if (jRadioButtonAutomated.isSelected() && cbJoinAutoIngestCluster.isSelected()) { + if (cbJoinAutoIngestCluster.isSelected()) { enableOptionsBasedOnMode(OptionsUiMode.AIM); } } @@ -1361,19 +1182,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,20 +1204,12 @@ 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; From 9b69a2a75a62c75d824bfc109d7308917751cedd Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 23 Oct 2017 14:53:24 -0400 Subject: [PATCH 03/69] 3153 enabled sorting of of AID tables and added Priority column to pending jobs --- .../autoingest/AutoIngestControlPanel.form | 3 - .../autoingest/AutoIngestControlPanel.java | 105 ++++++++++-------- 2 files changed, 57 insertions(+), 51 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.form b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.form index ad525e92ee..cec9d21492 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.form +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.form @@ -169,7 +169,6 @@ - @@ -193,7 +192,6 @@ - @@ -217,7 +215,6 @@ - diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index 891975223a..d87efb41ff 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -49,6 +49,7 @@ import javax.swing.UIManager; import javax.swing.event.ListSelectionEvent; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; import org.netbeans.api.options.OptionsDisplayer; import org.openide.DialogDisplayer; import org.openide.LifecycleManager; @@ -138,6 +139,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 = 50; + 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 +180,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { * ordinal or a column header string. */ @Messages({ + "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority=Priority", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Case=Case", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ImageFolder=Data Source", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.HostName=Host Name", @@ -203,8 +207,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 +231,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()}; } /** @@ -411,11 +416,16 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { column.setMaxWidth(TIME_COL_MAX_WIDTH); column.setPreferredWidth(TIME_COL_PREFERRED_WIDTH); column.setWidth(TIME_COL_PREFERRED_WIDTH); + + column = pendingTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader()); + column.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. */ - pendingTable.setAutoCreateRowSorter(false); + pendingTable.setAutoCreateRowSorter(true); /* * Create a row selection listener to enable/disable the prioritize @@ -454,7 +464,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 +534,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; } @@ -550,7 +560,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { 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. */ @@ -605,7 +615,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { /* * Prevent sorting when a column header is clicked. */ - completedTable.setAutoCreateRowSorter(false); + completedTable.setAutoCreateRowSorter(true); /* * Create a row selection listener to enable/disable the delete case and @@ -1030,9 +1040,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 +1051,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 +1097,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 +1118,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; @@ -1156,7 +1166,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { ((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(), + job.getPriority()}); // MANIFEST_FILE_PATH } } catch (Exception ex) { SYS_LOGGER.log(Level.SEVERE, "Dashboard error refreshing table", ex); @@ -1168,9 +1179,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); } /** @@ -1211,7 +1222,6 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { pendingTable.setModel(pendingTableModel); pendingTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.pendingTable.toolTipText")); // NOI18N - pendingTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS); pendingTable.setRowHeight(20); pendingTable.setSelectionModel(new DefaultListSelectionModel() { private static final long serialVersionUID = 1L; @@ -1229,7 +1239,6 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { runningTable.setModel(runningTableModel); runningTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.runningTable.toolTipText")); // NOI18N - runningTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS); runningTable.setRowHeight(20); runningTable.setSelectionModel(new DefaultListSelectionModel() { private static final long serialVersionUID = 1L; @@ -1247,7 +1256,6 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { completedTable.setModel(completedTableModel); completedTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.completedTable.toolTipText")); // NOI18N - completedTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS); completedTable.setRowHeight(20); completedTable.setSelectionModel(new DefaultListSelectionModel() { private static final long serialVersionUID = 1L; @@ -1425,10 +1433,10 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { .addComponent(completedScrollPane, 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, 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(bnCancelJob, javax.swing.GroupLayout.PREFERRED_SIZE, 117, Short.MAX_VALUE) + .addComponent(bnShowProgress, javax.swing.GroupLayout.PREFERRED_SIZE, 116, Short.MAX_VALUE) + .addComponent(bnCancelModule, javax.swing.GroupLayout.PREFERRED_SIZE, 117, Short.MAX_VALUE) + .addComponent(bnDeleteCase, javax.swing.GroupLayout.PREFERRED_SIZE, 117, Short.MAX_VALUE) .addComponent(bnShowCaseLog, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(bnReprocessJob, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) .addGroup(layout.createSequentialGroup() @@ -1535,11 +1543,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 +1564,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 +1711,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 +1740,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 +1771,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,11 +1800,11 @@ 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()); From 9b5dca32ae6604ef941b8096d3ad12308fb28e4c Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 23 Oct 2017 18:18:03 -0400 Subject: [PATCH 04/69] 3153 fixed issue with completed jobs re-ordering upon reprocess --- .../autoingest/AutoIngestControlPanel.java | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index d87efb41ff..22b758f2fc 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -39,17 +39,19 @@ 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; import javax.swing.JTable; +import javax.swing.RowSorter; +import static javax.swing.SortOrder.DESCENDING; import javax.swing.SwingWorker; import javax.swing.UIManager; import javax.swing.event.ListSelectionEvent; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableColumn; -import javax.swing.table.TableModel; +import javax.swing.table.TableRowSorter; import org.netbeans.api.options.OptionsDisplayer; import org.openide.DialogDisplayer; import org.openide.LifecycleManager; @@ -140,7 +142,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { 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 = 50; - private static final int PRIORITY_COLUMN_MAX_WIDTH=150; + 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; @@ -290,7 +292,6 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { return false; } }; - initComponents(); // Generated code. setServicesStatusMessage(); initPendingJobsTable(); @@ -298,6 +299,13 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { initCompletedJobsTable(); initButtons(); + @SuppressWarnings("unchecked") + TableRowSorter sorter = (TableRowSorter) completedTable.getRowSorter(); + List list = new ArrayList<>(); + list.add(new RowSorter.SortKey(JobsTableModelColumns.COMPLETED_TIME.ordinal(), DESCENDING)); + sorter.setSortKeys(list); + sorter.sort(); + /* * Must set this flag, otherwise pop up menus don't close properly. */ @@ -416,7 +424,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { column.setMaxWidth(TIME_COL_MAX_WIDTH); column.setPreferredWidth(TIME_COL_PREFERRED_WIDTH); column.setWidth(TIME_COL_PREFERRED_WIDTH); - + column = pendingTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader()); column.setMaxWidth(PRIORITY_COLUMN_MAX_WIDTH); column.setPreferredWidth(PRIORITY_COLUMN_PREFERRED_WIDTH); @@ -554,10 +562,10 @@ 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())); @@ -992,7 +1000,6 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { List 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)); } } @@ -1041,7 +1048,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { if (null != pendingJobs) { Path currentRow = getSelectedEntry(pendingTable); - refreshTable(pendingJobs, (DefaultTableModel)pendingTable.getModel(), null); + refreshTable(pendingJobs, (DefaultTableModel) pendingTable.getModel(), null); setSelectedEntry(pendingTable, currentRow); } @@ -1052,14 +1059,14 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { updateRunningTableButtonsBasedOnSelectedRow(); } Path currentRow = getSelectedEntry(runningTable); - refreshTable(runningJobs, (DefaultTableModel)runningTable.getModel(), null); - setSelectedEntry(runningTable, currentRow); + refreshTable(runningJobs, (DefaultTableModel) runningTable.getModel(), null); + setSelectedEntry(runningTable, currentRow); } if (null != completedJobs) { Path currentRow = getSelectedEntry(completedTable); - refreshTable(completedJobs, (DefaultTableModel)completedTable.getModel(), null); - setSelectedEntry(completedTable, currentRow); + refreshTable(completedJobs, (DefaultTableModel) completedTable.getModel(), null); + setSelectedEntry(completedTable, currentRow); } } @@ -1179,9 +1186,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { */ private void refreshTables() { JobsSnapshot jobsSnapshot = manager.getCurrentJobsSnapshot(); - refreshTable(jobsSnapshot.getCompletedJobs(), (DefaultTableModel)completedTable.getModel(), null); - refreshTable(jobsSnapshot.getPendingJobs(), (DefaultTableModel)pendingTable.getModel(), null); - refreshTable(jobsSnapshot.getRunningJobs(), (DefaultTableModel)runningTable.getModel(), null); + refreshTable(jobsSnapshot.getCompletedJobs(), (DefaultTableModel) completedTable.getModel(), null); + refreshTable(jobsSnapshot.getPendingJobs(), (DefaultTableModel) pendingTable.getModel(), null); + refreshTable(jobsSnapshot.getRunningJobs(), (DefaultTableModel) runningTable.getModel(), null); } /** @@ -1713,7 +1720,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { private void bnPrioritizeCaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnPrioritizeCaseActionPerformed if (pendingTable.getModel().getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) { this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - + String caseName = (pendingTable.getModel().getValueAt(pendingTable.convertRowIndexToModel(pendingTable.getSelectedRow()), JobsTableModelColumns.CASE.ordinal())).toString(); try { manager.prioritizeCase(caseName); From 3a555648d608fb3f6dab8653be1a5188e65a5504 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Tue, 24 Oct 2017 14:32:33 -0400 Subject: [PATCH 05/69] Minor clean-up and bug fixes. --- .../autopsy/casemodule/Bundle.properties | 18 ++++---- .../casemodule/CaseOpenMultiUserAction.java | 27 ++++++----- .../autopsy/casemodule/CueBannerPanel.java | 10 ++--- .../autopsy/casemodule/MultiUserCase.java | 45 ++++++++++++++----- .../casemodule/MultiUserCaseManager.java | 6 +++ ...asePanel.form => MultiUserCasesPanel.form} | 18 ++++---- ...asePanel.java => MultiUserCasesPanel.java} | 42 ++++++++--------- 7 files changed, 96 insertions(+), 70 deletions(-) rename Core/src/org/sleuthkit/autopsy/casemodule/{MultiUserCasePanel.form => MultiUserCasesPanel.form} (91%) rename Core/src/org/sleuthkit/autopsy/casemodule/{MultiUserCasePanel.java => MultiUserCasesPanel.java} (92%) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index 6ce0c76f3d..d23d86d6f8 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -235,15 +235,15 @@ ReviewModeCasePanel.CreatedTimeHeaderText=Created Time ReviewModeCasePanel.StatusIconHeaderText=Status ReviewModeCasePanel.OutputFolderHeaderText=Output Folder ReviewModeCasePanel.LastAccessedTimeHeaderText=Last Accessed Time -MultiUserCasePanel.rbDays.text=Days -MultiUserCasePanel.rbWeeks.text=Weeks -MultiUserCasePanel.rbMonths.text=Months -MultiUserCasePanel.rbAllCases.text=Everything -MultiUserCasePanel.bnRefresh.text=&Refresh -MultiUserCasePanel.bnOpen.text=&Open -MultiUserCasePanel.bnShowLog.toolTipText=Display case log file for selected case -MultiUserCasePanel.bnShowLog.text=&Show Auto Ingest Case Log -MultiUserCasePanel.rbGroupLabel.text=Show cases accessed in the last 10: 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 diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java index aa9b0eac6a..4d3af01f26 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java @@ -31,16 +31,13 @@ import org.openide.awt.ActionRegistration; import org.openide.util.HelpCtx; import org.openide.util.NbBundle; import org.openide.util.actions.CallableSystemAction; -import org.openide.util.lookup.ServiceProvider; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.core.UserPreferences; -import static org.sleuthkit.autopsy.core.UserPreferences.SelectedMode.REVIEW; import org.sleuthkit.autopsy.coreutils.NetworkUtils; /** - * The action associated with the Case/Open Case menu item via the layer.xml - * file, a toolbar button, and the Create New Case button of the start up window - * that allows a user to open a case. It opens an existing case. + * 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). */ @@ -57,14 +54,13 @@ public final class CaseOpenMultiUserAction extends CallableSystemAction implemen private static final String LOCAL_HOST_NAME = NetworkUtils.getLocalHostName(); private static final String REVIEW_MODE_TITLE = "Open Multi-User Case (" + LOCAL_HOST_NAME + ")"; + public CaseOpenMultiUserAction() {} + /** - * Constructs the action associated with the Case/Open Case menu item via - * the layer.xml file, a toolbar button, and the Create New Case button of - * the start up window that allows a user to open a case. It opens an - * existing case. - * + * Constructs the Multi-User Cases window used by the Open Multi-User Case + * menu item. */ - public CaseOpenMultiUserAction() { + private void initMultiUserCasesWindow() { multiUserCaseWindow = new JDialog( WindowManager.getDefault().getMainWindow(), REVIEW_MODE_TITLE, @@ -74,7 +70,7 @@ public final class CaseOpenMultiUserAction extends CallableSystemAction implemen multiUserCaseWindow.setVisible(false); }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW); - multiUserCaseWindow.add(new MultiUserCasePanel()); + multiUserCaseWindow.add(new MultiUserCasesPanel()); multiUserCaseWindow.pack(); multiUserCaseWindow.setResizable(false); } @@ -91,13 +87,16 @@ public final class CaseOpenMultiUserAction extends CallableSystemAction implemen } /** - * Pops up a file chooser to allow the user to select a case metadata file - * (.aut file) and attempts to open the case described by the file. + * Pops up a case selection panel to allow the user to selecte a multi-user + * case to open. * * @param e The action event. */ @Override public void actionPerformed(ActionEvent event) { + if(multiUserCaseWindow == null) { + initMultiUserCasesWindow(); + } multiUserCaseWindow.setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); multiUserCaseWindow.setVisible(true); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java index 48e54a3f9f..ff25e934cf 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java @@ -31,7 +31,6 @@ import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.core.UserPreferences; -import org.sleuthkit.autopsy.coreutils.NetworkUtils; /* * The panel in the default Autopsy startup window. @@ -39,8 +38,7 @@ 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 = "Open Multi-User Case (" + LOCAL_HOST_NAME + ")"; + private static final String REVIEW_MODE_TITLE = "Open Multi-User Case"; /* * This is field is static for the sake of the closeOpenRecentCasesWindow * method. @@ -91,7 +89,6 @@ public class CueBannerPanel extends javax.swing.JPanel { private void customizeComponents() { initRecentCasesWindow(); - initMultiUserCasesWindow(); } private void initRecentCasesWindow() { @@ -127,7 +124,7 @@ public class CueBannerPanel extends javax.swing.JPanel { multiUserCaseWindow.setVisible(false); }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW); - multiUserCaseWindow.add(new MultiUserCasePanel()); + multiUserCaseWindow.add(new MultiUserCasesPanel()); multiUserCaseWindow.pack(); multiUserCaseWindow.setResizable(false); } @@ -306,6 +303,9 @@ public class CueBannerPanel extends javax.swing.JPanel { }//GEN-LAST:event_openRecentCaseButtonActionPerformed private void openMultiUserCaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openMultiUserCaseButtonActionPerformed + if(multiUserCaseWindow == null) { + initMultiUserCasesWindow(); + } multiUserCaseWindow.setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); multiUserCaseWindow.setVisible(true); }//GEN-LAST:event_openMultiUserCaseButtonActionPerformed diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java index d1a2bc65da..453c0bb27f 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java @@ -18,9 +18,11 @@ */ 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.Comparator; import java.util.Date; @@ -47,10 +49,19 @@ class MultiUserCase implements Comparable { * * @param caseDirectoryPath The case directory path. */ - MultiUserCase(Path caseDirectoryPath) { + MultiUserCase(Path caseDirectoryPath) throws CaseMetadata.CaseMetadataException { + CaseMetadata caseMetadata = null; + + try { + caseMetadata = getCaseMetadataFromCaseDirectoryPath(caseDirectoryPath); + } catch (CaseMetadata.CaseMetadataException ex) { + logger.log(Level.SEVERE, String.format("Error reading the case metadata for %s.", caseDirectoryPath), ex); + throw ex; + } + this.caseDirectoryPath = caseDirectoryPath; - caseName = getCaseNameFromCaseDirectoryPath(caseDirectoryPath); - metadataFilePath = caseDirectoryPath.resolve(caseName + CaseMetadata.getFileExtension()); + caseName = caseMetadata.getCaseDisplayName(); + metadataFilePath = caseDirectoryPath.resolve(caseMetadata.getCaseName() + CaseMetadata.getFileExtension()); BasicFileAttributes fileAttrs = null; try { fileAttrs = Files.readAttributes(metadataFilePath, BasicFileAttributes.class); @@ -119,19 +130,29 @@ class MultiUserCase implements Comparable { } /** - * Extracts the case name from a case folder path. + * Gets the case metadata from a case directory path. * - * @param caseFolderPath A case folder path. + * @param caseDirectoryPath The case directory path. * - * @return A case name, with the time stamp suffix removed. + * @return Case metadata. */ - static String getCaseNameFromCaseDirectoryPath(Path caseFolderPath) { - String caseName = caseFolderPath.getFileName().toString(); - if (caseName.length() > TimeStampUtils.getTimeStampLength()) { - return caseName.substring(0, caseName.length() - TimeStampUtils.getTimeStampLength()); - } else { - return caseName; + static CaseMetadata getCaseMetadataFromCaseDirectoryPath(Path caseDirectoryPath) throws CaseMetadata.CaseMetadataException { + CaseMetadata caseMetadata = null; + + File directory = new File(caseDirectoryPath.toString()); + if (directory.isDirectory()) { + String fileNamePrefix = directory.getName(); + if (TimeStampUtils.endsWithTimeStamp(fileNamePrefix)) { + fileNamePrefix = fileNamePrefix.substring(0, fileNamePrefix.length() - TimeStampUtils.getTimeStampLength()); + } + + File file = new File(directory + "/" + fileNamePrefix + CaseMetadata.getFileExtension()); + if(file.isFile()) { + caseMetadata = new CaseMetadata(Paths.get(file.getAbsolutePath())); + } } + + return caseMetadata; } /** diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java index ec3b42116d..5fa8b80f7b 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java @@ -23,6 +23,8 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; @@ -78,7 +80,11 @@ final class MultiUserCaseManager { if(caseFolder.exists()) { File[] autFiles = caseFolder.listFiles((dir, name) -> name.toLowerCase().endsWith(".aut")); if(autFiles != null && autFiles.length > 0) { + try { cases.add(new MultiUserCase(casePath)); + } catch (CaseMetadata.CaseMetadataException ex) { + // Ignore and continue. + } } } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form similarity index 91% rename from Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.form rename to Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form index a54439c4d3..179bc23bb8 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form @@ -82,7 +82,7 @@ - + @@ -118,7 +118,7 @@ - + @@ -153,7 +153,7 @@ - + @@ -165,10 +165,10 @@ - + - + @@ -182,7 +182,7 @@ - + @@ -196,7 +196,7 @@ - + @@ -209,7 +209,7 @@ - + @@ -222,7 +222,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java similarity index 92% rename from Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.java rename to Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java index 5f3365e8b1..6b20a41147 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java @@ -39,10 +39,10 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; /** * A panel that allows a user to open cases created by auto ingest. */ -public class MultiUserCasePanel extends javax.swing.JPanel { +public class MultiUserCasesPanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; - private static final Logger LOGGER = Logger.getLogger(MultiUserCasePanel.class.getName()); + private static final Logger LOGGER = Logger.getLogger(MultiUserCasesPanel.class.getName()); private static final String LOG_FILE_NAME = "auto_ingest_log.txt"; private static final MultiUserCase.LastAccessedDateDescendingComparator REVERSE_DATE_MODIFIED_COMPARATOR = new MultiUserCase.LastAccessedDateDescendingComparator(); private static final int CASE_COL_MIN_WIDTH = 30; @@ -62,11 +62,11 @@ public class MultiUserCasePanel extends javax.swing.JPanel { * 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(MultiUserCasePanel.class, "ReviewModeCasePanel.CaseHeaderText"); - private static final String CREATEDTIME_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "ReviewModeCasePanel.CreatedTimeHeaderText"); - private static final String COMPLETEDTIME_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "ReviewModeCasePanel.LastAccessedTimeHeaderText"); - private static final String STATUS_ICON_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "ReviewModeCasePanel.StatusIconHeaderText"); - private static final String OUTPUT_FOLDER_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasePanel.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"); enum COLUMN_HEADERS { @@ -86,7 +86,7 @@ public class MultiUserCasePanel extends javax.swing.JPanel { * * @param parent The parent dialog for this panel. */ - MultiUserCasePanel() { + MultiUserCasesPanel() { caseTableModel = new DefaultTableModel(columnNames, 0) { private static final long serialVersionUID = 1L; @@ -326,7 +326,7 @@ public class MultiUserCasePanel extends javax.swing.JPanel { setName("Completed Cases"); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(bnOpen, org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "MultiUserCasePanel.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) { @@ -346,7 +346,7 @@ public class MultiUserCasePanel extends javax.swing.JPanel { }); scrollPaneTable.setViewportView(casesTable); - org.openide.awt.Mnemonics.setLocalizedText(bnRefresh, org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "MultiUserCasePanel.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); @@ -355,7 +355,7 @@ public class MultiUserCasePanel extends javax.swing.JPanel { rbGroupHistoryLength.add(rbAllCases); rbAllCases.setSelected(true); - org.openide.awt.Mnemonics.setLocalizedText(rbAllCases, org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "MultiUserCasePanel.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); @@ -377,8 +377,8 @@ public class MultiUserCasePanel extends javax.swing.JPanel { .addComponent(rbAllCases)) ); - org.openide.awt.Mnemonics.setLocalizedText(bnShowLog, org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "MultiUserCasePanel.bnShowLog.text")); // NOI18N - bnShowLog.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "MultiUserCasePanel.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) { @@ -387,7 +387,7 @@ public class MultiUserCasePanel extends javax.swing.JPanel { }); rbGroupHistoryLength.add(rbDays); - org.openide.awt.Mnemonics.setLocalizedText(rbDays, org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "MultiUserCasePanel.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) { @@ -396,7 +396,7 @@ public class MultiUserCasePanel extends javax.swing.JPanel { }); rbGroupHistoryLength.add(rbWeeks); - org.openide.awt.Mnemonics.setLocalizedText(rbWeeks, org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "MultiUserCasePanel.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); @@ -404,7 +404,7 @@ public class MultiUserCasePanel extends javax.swing.JPanel { }); rbGroupHistoryLength.add(rbMonths); - org.openide.awt.Mnemonics.setLocalizedText(rbMonths, org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "MultiUserCasePanel.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); @@ -412,7 +412,7 @@ public class MultiUserCasePanel extends javax.swing.JPanel { }); rbGroupLabel.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(rbGroupLabel, org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "MultiUserCasePanel.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); @@ -521,14 +521,14 @@ public class MultiUserCasePanel extends javax.swing.JPanel { Desktop.getDesktop().edit(pathToLog.toFile()); } else { - JOptionPane.showMessageDialog(this, org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "DisplayLogDialog.cannotFindLog"), - org.openide.util.NbBundle.getMessage(MultiUserCasePanel.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); JOptionPane.showMessageDialog(this, - org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "DisplayLogDialog.cannotOpenLog"), - org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "DisplayLogDialog.unableToShowLogFile"), + org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.cannotOpenLog"), + org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.unableToShowLogFile"), JOptionPane.PLAIN_MESSAGE); } } From 98609be8f92b00f5fbc7c299ebe2822c0af3adf0 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Tue, 24 Oct 2017 14:39:07 -0400 Subject: [PATCH 06/69] Removed unused imports. --- Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java | 1 - .../org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java | 2 -- 2 files changed, 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java index 453c0bb27f..6220b84a80 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java @@ -28,7 +28,6 @@ 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; import org.sleuthkit.autopsy.coreutils.TimeStampUtils; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java index 5fa8b80f7b..0975e60ce3 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java @@ -23,8 +23,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; From 8e8b957f4c9c965fa7ba95283c0fb1719c8a2d46 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Tue, 24 Oct 2017 15:17:57 -0400 Subject: [PATCH 07/69] Bug fix regarding assumed AUT filename. --- .../autopsy/casemodule/MultiUserCase.java | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java index 6220b84a80..6a9ae04c12 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java @@ -145,9 +145,30 @@ class MultiUserCase implements Comparable { fileNamePrefix = fileNamePrefix.substring(0, fileNamePrefix.length() - TimeStampUtils.getTimeStampLength()); } - File file = new File(directory + "/" + fileNamePrefix + CaseMetadata.getFileExtension()); - if(file.isFile()) { - caseMetadata = new CaseMetadata(Paths.get(file.getAbsolutePath())); + /* + * Attempt to open an AUT file that has the folder name without a + * time stamp. + */ + File autFile = new File(directory + "/" + fileNamePrefix + CaseMetadata.getFileExtension()); + + /* + * If the AUT file doesn't exist, attempt to find an AUT file via a + * directory scan. + */ + if(!autFile.isFile()) { + for (File file : directory.listFiles()) { + if (file.getName().toLowerCase().endsWith(CaseMetadata.getFileExtension()) && file.isFile()) { + autFile = file; + break; + } + } + } + + /* + * If the AUT file has been found, grab the case metadata. + */ + if(autFile.isFile()) { + caseMetadata = new CaseMetadata(Paths.get(autFile.getAbsolutePath())); } } From 71dfdca9b13aa05751c9a1e3d98ed86ec586e7ae Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 24 Oct 2017 17:28:24 -0400 Subject: [PATCH 08/69] 3153 change priority column to prioritized flag column, fix priority saving bug --- .../autoingest/AutoIngestControlPanel.java | 64 +++++++++++-------- .../autoingest/AutoIngestManager.java | 19 ++++-- .../PrioritizedIconCellRenderer.java | 58 +++++++++++++++++ 3 files changed, 107 insertions(+), 34 deletions(-) create mode 100644 Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index 22b758f2fc..fa0ec8e065 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -141,7 +141,7 @@ 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 = 50; + 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; @@ -182,7 +182,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { * ordinal or a column header string. */ @Messages({ - "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority=Priority", + "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority=Prioritized", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Case=Case", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ImageFolder=Data Source", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.HostName=Host Name", @@ -266,32 +266,12 @@ 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; + completedTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0); - @Override - public boolean isCellEditable(int row, int column) { - return false; - } - }; - - completedTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) { - private static final long serialVersionUID = 1L; - - @Override - public boolean isCellEditable(int row, int column) { - return false; - } - }; initComponents(); // Generated code. setServicesStatusMessage(); initPendingJobsTable(); @@ -426,12 +406,13 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { 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(true); @@ -621,7 +602,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { column.setWidth(STATUS_COL_PREFERRED_WIDTH); /* - * Prevent sorting when a column header is clicked. + * Allow sorting when a column header is clicked. */ completedTable.setAutoCreateRowSorter(true); @@ -1846,4 +1827,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); + } + } + } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index c5f43a8f1f..9f43879b55 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -503,6 +503,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); } @@ -558,10 +559,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); } catch (CoordinationServiceException | InterruptedException ex) { + job.setPriority(oldPriority); throw new AutoIngestManagerException("Error updating case priority", ex); } } @@ -612,12 +615,14 @@ public final class AutoIngestManager extends Observable implements PropertyChang */ if (null != prioritizedJob) { ++maxPriority; + int oldPriority = prioritizedJob.getPriority(); + prioritizedJob.setPriority(maxPriority); try { this.updateCoordinationServiceNode(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()); @@ -1046,8 +1051,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(); @@ -1061,8 +1066,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()); @@ -1082,7 +1087,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang break; case DELETED: /* - * Ignore jobs marked as "deleted." + * Ignore jobs marked as "deleted." */ break; default: diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java new file mode 100644 index 0000000000..11127093ac --- /dev/null +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java @@ -0,0 +1,58 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2017 Basis Technology Corp. + * Contact: carrier sleuthkit 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.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 whether the priority value of a job + * has ever been increased, tick if prioritized nothing if not. + */ +class PrioritizedIconCellRenderer extends GrayableCellRenderer { + + + @Messages({ + "PrioritizedIconCellRenderer.prioritized.tooltiptext=This job has been prioritised. The most recently prioritised 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)); + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + setHorizontalAlignment(CENTER); + if ((value instanceof Integer)) { + if ((int) value == 0) { + setIcon(null); + setToolTipText(org.openide.util.NbBundle.getMessage(CaseStatusIconCellRenderer.class, "PrioritizedIconCellRenderer.notPrioritized.tooltiptext")); + } else { + setIcon(checkedIcon); + setToolTipText(org.openide.util.NbBundle.getMessage(CaseStatusIconCellRenderer.class, "PrioritizedIconCellRenderer.prioritized.tooltiptext")); + } + } + grayCellIfTableNotEnabled(table, isSelected); + + return this; + } +} From 1402e683b59db69de50bc77dc93ab669865e2f17 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 24 Oct 2017 17:41:13 -0400 Subject: [PATCH 09/69] 3153 fix spelling of prioritized --- .../experimental/autoingest/PrioritizedIconCellRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java index 11127093ac..8452e0fc22 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java @@ -33,7 +33,7 @@ class PrioritizedIconCellRenderer extends GrayableCellRenderer { @Messages({ - "PrioritizedIconCellRenderer.prioritized.tooltiptext=This job has been prioritised. The most recently prioritised job should be processed next.", + "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; From 5b080df30f945de7fffbc93b3686cc356c5b9c68 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 24 Oct 2017 19:08:29 -0400 Subject: [PATCH 10/69] 3153 put comment on correct line --- .../experimental/autoingest/AutoIngestControlPanel.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index fa0ec8e065..7499a770d7 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -1154,8 +1154,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { ((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(), - job.getPriority()}); // 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); From 0f5fb4cb5248312212b5fa1584a185b3fa379a66 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 24 Oct 2017 19:10:16 -0400 Subject: [PATCH 11/69] 3166 Sortable columns and prioritized column added to Aid 2.0 --- .../autoingest/AutoIngestDashboard.form | 3 -- .../autoingest/AutoIngestDashboard.java | 32 ++++++++++++------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.form b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.form index 4a943b4924..2ab9f9051c 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.form +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.form @@ -103,7 +103,6 @@ - @@ -127,7 +126,6 @@ - @@ -151,7 +149,6 @@ - diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java index 2d10dff258..edbefe51d7 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java @@ -55,6 +55,8 @@ public final class AutoIngestDashboard 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 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; @@ -243,10 +245,15 @@ public final class AutoIngestDashboard 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.setAutoCreateRowSorter(true); /* * Create a row selection listener to enable/disable the Prioritize @@ -257,8 +264,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 +287,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 +361,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. */ @@ -407,9 +414,9 @@ public final class AutoIngestDashboard extends JPanel implements Observer { 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.setAutoCreateRowSorter(true); } /** @@ -476,6 +483,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer { ((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,7 +549,8 @@ 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")), HOST_NAME(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.HostName")), @@ -553,6 +562,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 +587,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer { STAGE_TIME.getColumnHeader(), CASE_DIRECTORY_PATH.getColumnHeader(), MANIFEST_FILE_PATH.getColumnHeader(), + PRIORITY.getColumnHeader(), JOB.getColumnHeader() }; }; @@ -667,7 +678,6 @@ public final class AutoIngestDashboard extends JPanel implements Observer { 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 +695,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 +712,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; From 405fc296461e8691c50109554628a23c63c50a66 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 25 Oct 2017 14:54:45 -0400 Subject: [PATCH 12/69] Minor code revisions. --- .../autopsy/casemodule/MultiUserCase.java | 80 +++++++++++++------ .../casemodule/MultiUserCaseManager.java | 2 +- 2 files changed, 58 insertions(+), 24 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java index 6a9ae04c12..a85eeeb9df 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java @@ -47,8 +47,15 @@ class MultiUserCase implements Comparable { * Constructs a representation of case created by automated ingest. * * @param caseDirectoryPath The case directory path. + * + * @throws CaseMetadata.CaseMetadataException If the CaseMetadata object + * cannot be constructed for the + * case display name. + * @throws MultiUserCaseException If no case metadata (.aut) + * file is found in the case + * directory. */ - MultiUserCase(Path caseDirectoryPath) throws CaseMetadata.CaseMetadataException { + MultiUserCase(Path caseDirectoryPath) throws CaseMetadata.CaseMetadataException, MultiUserCaseException { CaseMetadata caseMetadata = null; try { @@ -60,7 +67,7 @@ class MultiUserCase implements Comparable { this.caseDirectoryPath = caseDirectoryPath; caseName = caseMetadata.getCaseDisplayName(); - metadataFilePath = caseDirectoryPath.resolve(caseMetadata.getCaseName() + CaseMetadata.getFileExtension()); + metadataFilePath = caseMetadata.getFilePath(); BasicFileAttributes fileAttrs = null; try { fileAttrs = Files.readAttributes(metadataFilePath, BasicFileAttributes.class); @@ -134,8 +141,14 @@ class MultiUserCase implements Comparable { * @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. */ - static CaseMetadata getCaseMetadataFromCaseDirectoryPath(Path caseDirectoryPath) throws CaseMetadata.CaseMetadataException { + private static CaseMetadata getCaseMetadataFromCaseDirectoryPath(Path caseDirectoryPath) throws CaseMetadata.CaseMetadataException, MultiUserCaseException { CaseMetadata caseMetadata = null; File directory = new File(caseDirectoryPath.toString()); @@ -145,31 +158,23 @@ class MultiUserCase implements Comparable { fileNamePrefix = fileNamePrefix.substring(0, fileNamePrefix.length() - TimeStampUtils.getTimeStampLength()); } - /* - * Attempt to open an AUT file that has the folder name without a - * time stamp. - */ - File autFile = new File(directory + "/" + fileNamePrefix + CaseMetadata.getFileExtension()); + File autFile = null; /* - * If the AUT file doesn't exist, attempt to find an AUT file via a - * directory scan. + * Attempt to find an AUT file via a directory scan. */ - if(!autFile.isFile()) { - for (File file : directory.listFiles()) { - if (file.getName().toLowerCase().endsWith(CaseMetadata.getFileExtension()) && file.isFile()) { - autFile = file; - break; - } + for (File file : directory.listFiles()) { + if (file.getName().toLowerCase().endsWith(CaseMetadata.getFileExtension()) && file.isFile()) { + autFile = file; + break; } } - /* - * If the AUT file has been found, grab the case metadata. - */ - if(autFile.isFile()) { - caseMetadata = new CaseMetadata(Paths.get(autFile.getAbsolutePath())); + 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; @@ -210,7 +215,7 @@ class MultiUserCase implements Comparable { /** * Compares this AutopIngestCase object with abnother MultiUserCase object - for order. + * for order. */ @Override public int compareTo(MultiUserCase other) { @@ -224,7 +229,7 @@ class MultiUserCase implements Comparable { /** * Compares two MultiUserCase objects for order based on last accessed - date (descending). + * date (descending). * * @param object The first MultiUserCase object * @param otherObject The second AuotIngestCase object. @@ -237,6 +242,35 @@ class MultiUserCase implements Comparable { return -object.getLastAccessedDate().compareTo(otherObject.getLastAccessedDate()); } } + + /** + * Exception thrown when there is a problem creating a multi-user case. + */ + final static 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); + } + } enum CaseStatus { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java index 0975e60ce3..3101461443 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java @@ -80,7 +80,7 @@ final class MultiUserCaseManager { if(autFiles != null && autFiles.length > 0) { try { cases.add(new MultiUserCase(casePath)); - } catch (CaseMetadata.CaseMetadataException ex) { + } catch (CaseMetadata.CaseMetadataException | MultiUserCase.MultiUserCaseException ex) { // Ignore and continue. } } From 6d42d16191f50b8f6200fe5977c3d15f8b2bb98e Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 25 Oct 2017 17:28:47 -0400 Subject: [PATCH 13/69] 3153 - Date Columns in AID now sort by descending order first --- .../autoingest/AutoIngestControlPanel.java | 45 ++++++++++++++----- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index 7499a770d7..26dcabff58 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -45,7 +45,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTable; import javax.swing.RowSorter; -import static javax.swing.SortOrder.DESCENDING; +import javax.swing.SortOrder; import javax.swing.SwingWorker; import javax.swing.UIManager; import javax.swing.event.ListSelectionEvent; @@ -278,14 +278,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { initRunningJobsTable(); initCompletedJobsTable(); initButtons(); - - @SuppressWarnings("unchecked") - TableRowSorter sorter = (TableRowSorter) completedTable.getRowSorter(); - List list = new ArrayList<>(); - list.add(new RowSorter.SortKey(JobsTableModelColumns.COMPLETED_TIME.ordinal(), DESCENDING)); - sorter.setSortKeys(list); - sorter.sort(); - + completedTable.getRowSorter().toggleSortOrder(JobsTableModelColumns.COMPLETED_TIME.ordinal()); /* * Must set this flag, otherwise pop up menus don't close properly. */ @@ -414,7 +407,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { /** * Allow sorting when a column header is clicked. */ - pendingTable.setAutoCreateRowSorter(true); + pendingTable.setRowSorter(new AutoIngestTableRowSorter<>(pendingTableModel)); /* * Create a row selection listener to enable/disable the prioritize @@ -604,7 +597,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { /* * Allow sorting when a column header is clicked. */ - completedTable.setAutoCreateRowSorter(true); + completedTable.setRowSorter(new AutoIngestTableRowSorter<>(completedTableModel)); /* * Create a row selection listener to enable/disable the delete case and @@ -1856,4 +1849,34 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { } } } + + /** + * RowSorter which makes columns whose type is Date to be sorted first in + * Descending order then in Ascending order + */ + private class AutoIngestTableRowSorter extends TableRowSorter { + + private AutoIngestTableRowSorter(M tModel) { + super(tModel); + } + + @Override + public void toggleSortOrder(int column) { + if (!this.getModel().getColumnClass(column).equals(Date.class)) { + super.toggleSortOrder(column); //if it isn't a date perform the regular sorting + } else { + ArrayList 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); + } + } + } } From 34c705252769d36cb5a6cafd92a39df692087fad Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 25 Oct 2017 18:18:50 -0400 Subject: [PATCH 14/69] 3166 Applied the date column sorting chages from 3153 to AID 2.0 and AutoIngestCasePanel --- .../autoingest/AutoIngestCasePanel.form | 2 - .../autoingest/AutoIngestCasePanel.java | 4 +- .../autoingest/AutoIngestControlPanel.java | 34 ---------- .../autoingest/AutoIngestDashboard.java | 67 ++++++++++--------- .../autoingest/AutoIngestRowSorter.java | 56 ++++++++++++++++ 5 files changed, 94 insertions(+), 69 deletions(-) create mode 100644 Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestRowSorter.java diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.form b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.form index cb0f275809..f5963ff59d 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.form +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.form @@ -99,11 +99,9 @@ - - diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java index 9b6b3ddefa..0a847dbd0e 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java @@ -150,7 +150,7 @@ public final class AutoIngestCasePanel extends JPanel { theColumn.setWidth(STATUS_COL_PREFERRED_WIDTH); casesTable.removeColumn(casesTable.getColumn(OUTPUT_FOLDER_HEADER)); - + casesTable.setRowSorter(new AutoIngestTableRowSorter<>(caseTableModel)); /* * Listen for row selection changes and set button state for the current * selection. @@ -408,9 +408,7 @@ public final class AutoIngestCasePanel extends JPanel { } }); - 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() { diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index 26dcabff58..aa47fb3271 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -39,19 +39,15 @@ import javax.swing.DefaultListSelectionModel; import java.awt.Color; import java.beans.PropertyChangeEvent; import java.io.File; - import java.util.logging.Logger; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTable; -import javax.swing.RowSorter; -import javax.swing.SortOrder; import javax.swing.SwingWorker; import javax.swing.UIManager; import javax.swing.event.ListSelectionEvent; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableColumn; -import javax.swing.table.TableRowSorter; import org.netbeans.api.options.OptionsDisplayer; import org.openide.DialogDisplayer; import org.openide.LifecycleManager; @@ -1849,34 +1845,4 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { } } } - - /** - * RowSorter which makes columns whose type is Date to be sorted first in - * Descending order then in Ascending order - */ - private class AutoIngestTableRowSorter extends TableRowSorter { - - private AutoIngestTableRowSorter(M tModel) { - super(tModel); - } - - @Override - public void toggleSortOrder(int column) { - if (!this.getModel().getColumnClass(column).equals(Date.class)) { - super.toggleSortOrder(column); //if it isn't a date perform the regular sorting - } else { - ArrayList 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); - } - } - } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java index edbefe51d7..8222ccc1a6 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java @@ -48,7 +48,7 @@ import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestMonitor.JobsSnaps /** * 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; @@ -102,32 +102,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(); @@ -250,10 +229,10 @@ public final class AutoIngestDashboard extends JPanel implements Observer { 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(true); + pendingTable.setRowSorter(new AutoIngestRowSorter<>(pendingTableModel)); /* * Create a row selection listener to enable/disable the Prioritize @@ -412,11 +391,10 @@ public final class AutoIngestDashboard extends JPanel implements Observer { column.setMaxWidth(STATUS_COL_MAX_WIDTH); column.setPreferredWidth(STATUS_COL_PREFERRED_WIDTH); column.setWidth(STATUS_COL_PREFERRED_WIDTH); - /* * Allow sorting when a column header is clicked. */ - completedTable.setAutoCreateRowSorter(true); + completedTable.setRowSorter(new AutoIngestRowSorter<>(completedTableModel)); } /** @@ -550,7 +528,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer { */ private enum JobsTableModelColumns { @Messages({"AutoIngestDashboard.JobsTableModel.ColumnHeader.Priority=Prioritized"}) - + CASE(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Case")), DATA_SOURCE(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.ImageFolder")), HOST_NAME(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.HostName")), @@ -898,4 +876,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); + } + } + } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestRowSorter.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestRowSorter.java new file mode 100644 index 0000000000..c866b2d7f6 --- /dev/null +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestRowSorter.java @@ -0,0 +1,56 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2017 Basis Technology Corp. + * Contact: carrier sleuthkit 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 + */ +final class AutoIngestTableRowSorter extends TableRowSorter { + + AutoIngestTableRowSorter(M tModel) { + super(tModel); + } + + @Override + public void toggleSortOrder(int column) { + if (!this.getModel().getColumnClass(column).equals(Date.class)) { + super.toggleSortOrder(column); //if it isn't a date perform the regular sorting + } else { + ArrayList 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); + } + } +} From 8a759d26fe83a1f069b00f8cdc05d85ccd584cc6 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 25 Oct 2017 18:41:26 -0400 Subject: [PATCH 15/69] 3166 fix incorrect rename of some methods from AutoIngestRowSorter refactor --- .../autopsy/experimental/autoingest/AutoIngestCasePanel.java | 2 +- .../experimental/autoingest/AutoIngestControlPanel.java | 4 ++-- .../autopsy/experimental/autoingest/AutoIngestRowSorter.java | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java index 0a847dbd0e..1be3430910 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java @@ -150,7 +150,7 @@ public final class AutoIngestCasePanel extends JPanel { theColumn.setWidth(STATUS_COL_PREFERRED_WIDTH); casesTable.removeColumn(casesTable.getColumn(OUTPUT_FOLDER_HEADER)); - casesTable.setRowSorter(new AutoIngestTableRowSorter<>(caseTableModel)); + casesTable.setRowSorter(new AutoIngestRowSorter<>(caseTableModel)); /* * Listen for row selection changes and set button state for the current * selection. diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index aa47fb3271..b299b89e01 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -403,7 +403,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { /** * Allow sorting when a column header is clicked. */ - pendingTable.setRowSorter(new AutoIngestTableRowSorter<>(pendingTableModel)); + pendingTable.setRowSorter(new AutoIngestRowSorter<>(pendingTableModel)); /* * Create a row selection listener to enable/disable the prioritize @@ -593,7 +593,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { /* * Allow sorting when a column header is clicked. */ - completedTable.setRowSorter(new AutoIngestTableRowSorter<>(completedTableModel)); + completedTable.setRowSorter(new AutoIngestRowSorter<>(completedTableModel)); /* * Create a row selection listener to enable/disable the delete case and diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestRowSorter.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestRowSorter.java index c866b2d7f6..7334e31229 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestRowSorter.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestRowSorter.java @@ -29,9 +29,9 @@ import javax.swing.table.TableRowSorter; * RowSorter which makes columns whose type is Date to be sorted first in * Descending order then in Ascending order */ -final class AutoIngestTableRowSorter extends TableRowSorter { +class AutoIngestRowSorter extends TableRowSorter { - AutoIngestTableRowSorter(M tModel) { + AutoIngestRowSorter(M tModel) { super(tModel); } From 3c66cc242b3e417570f08499292e01ccb185c57f Mon Sep 17 00:00:00 2001 From: millmanorama Date: Thu, 26 Oct 2017 17:11:11 +0200 Subject: [PATCH 16/69] set initial sort to Priority and initialize toolbar from GroupManager --- .../autopsy/imagegallery/datamodel/grouping/GroupManager.java | 4 ++-- .../src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java index ae9e17bb4a..8a934cda98 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java @@ -122,7 +122,7 @@ public class GroupManager { /* * --- current grouping/sorting attributes --- */ - private volatile GroupSortBy sortBy = GroupSortBy.NONE; + private volatile GroupSortBy sortBy = GroupSortBy.PRIORITY; private volatile DrawableAttribute groupBy = DrawableAttribute.PATH; private volatile SortOrder sortOrder = SortOrder.ASCENDING; @@ -466,7 +466,7 @@ public class GroupManager { } } - public Comparator getSortBy() { + public GroupSortBy getSortBy() { return sortBy; } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java index 2dc85cbfd9..90c739287e 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java @@ -189,7 +189,7 @@ public class Toolbar extends ToolBar { }); sortChooser.sortOrderProperty().addListener(queryInvalidationListener); - sortChooser.setComparator(GroupSortBy.PRIORITY); + sortChooser.setComparator(controller.getGroupManager().getSortBy()); getItems().add(1, sortChooser); sortHelpImageView.setCursor(Cursor.HAND); From 3f325a86fd118d68b7106af4ed7cb6b87912a8cd Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Thu, 26 Oct 2017 15:52:19 -0400 Subject: [PATCH 17/69] Various bug fixes. --- .../autopsy/casemodule/CaseDeleteAction.java | 3 +-- .../autopsy/casemodule/CaseMetadata.java | 11 ++++++++++ .../casemodule/CaseOpenMultiUserAction.java | 2 +- .../autopsy/casemodule/CueBannerPanel.java | 2 +- .../autopsy/casemodule/MultiUserCase.java | 9 ++++++++ .../casemodule/MultiUserCasesPanel.java | 22 ++++++++++++++----- .../autopsy/core/UserPreferences.java | 12 +++++++--- .../autoingest/AutoIngestCaseOpenAction.java | 1 - .../AutoIngestDashboardOpenAction.java | 1 - .../autoingest/CaseImportPanel.java | 1 - 10 files changed, 48 insertions(+), 16 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseDeleteAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseDeleteAction.java index 3ef30f2594..dcda423c18 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseDeleteAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseDeleteAction.java @@ -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; /** @@ -51,7 +50,7 @@ final class CaseDeleteAction extends CallableSystemAction { 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); + setEnabled(null != evt.getNewValue() && ((Case)evt.getNewValue()).getCaseType() != Case.CaseType.MULTI_USER_CASE); }); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java index 1f4c5b7912..dee10f0ca1 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java @@ -172,6 +172,17 @@ public final class CaseMetadata { public String getCaseDirectory() { return metadataFilePath.getParent().toString(); } + + /** + * Gets the full case directory path. + * + * @return The case directory path. + */ + public String getCaseDirectoryPath() { + String fileName = metadataFilePath.getFileName().toString(); + String caseDirectoryPath = metadataFilePath.toString(); + return caseDirectoryPath.substring(0, caseDirectoryPath.lastIndexOf(fileName)); + } /** * Gets the case type. diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java index 4d3af01f26..96892cbb4e 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java @@ -70,7 +70,7 @@ public final class CaseOpenMultiUserAction extends CallableSystemAction implemen multiUserCaseWindow.setVisible(false); }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW); - multiUserCaseWindow.add(new MultiUserCasesPanel()); + multiUserCaseWindow.add(MultiUserCasesPanel.getInstance()); multiUserCaseWindow.pack(); multiUserCaseWindow.setResizable(false); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java index ff25e934cf..7a1c32db85 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java @@ -124,7 +124,7 @@ public class CueBannerPanel extends javax.swing.JPanel { multiUserCaseWindow.setVisible(false); }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW); - multiUserCaseWindow.add(new MultiUserCasesPanel()); + multiUserCaseWindow.add(MultiUserCasesPanel.getInstance()); multiUserCaseWindow.pack(); multiUserCaseWindow.setResizable(false); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java index a85eeeb9df..8ecc1c91e2 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java @@ -120,6 +120,15 @@ class MultiUserCase implements Comparable { Date getLastAccessedDate() { return this.lastAccessedDate; } + + /** + * Gets the full path of the metadata (.aut) file. + * + * @return The metadata file path. + */ + Path getMetadataFilePath() { + return this.metadataFilePath; + } /** * Gets the status of this case based on the auto ingest result file in the diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java index 6b20a41147..aa2f199967 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java @@ -79,6 +79,18 @@ public class MultiUserCasesPanel extends javax.swing.JPanel { private final String[] columnNames = {CASE_HEADER, CREATEDTIME_HEADER, COMPLETEDTIME_HEADER, STATUS_ICON_HEADER, OUTPUT_FOLDER_HEADER}; private DefaultTableModel caseTableModel; private Path currentlySelectedCase = null; + private static MultiUserCasesPanel instance; + + /* + * Gets the singleton instance of the panel. + */ + static MultiUserCasesPanel getInstance() { + if (instance == null) { + instance = new MultiUserCasesPanel(); + } + instance.refreshCasesTable(); + return instance; + } /** * Constructs a panel that allows a user to open cases created by automated @@ -86,7 +98,7 @@ public class MultiUserCasesPanel extends javax.swing.JPanel { * * @param parent The parent dialog for this panel. */ - MultiUserCasesPanel() { + private MultiUserCasesPanel() { caseTableModel = new DefaultTableModel(columnNames, 0) { private static final long serialVersionUID = 1L; @@ -174,7 +186,7 @@ public class MultiUserCasesPanel extends javax.swing.JPanel { autoIngestCase.getCreationDate(), autoIngestCase.getLastAccessedDate(), (MultiUserCase.CaseStatus.OK != autoIngestCase.getStatus()), - autoIngestCase.getCaseDirectoryPath().toString()}); + autoIngestCase.getMetadataFilePath().toString()}); } } setSelectedCase(currentlySelectedCase); @@ -472,8 +484,7 @@ public class MultiUserCasesPanel extends javax.swing.JPanel { 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()); + COLUMN_HEADERS.OUTPUTFOLDER.ordinal())); new Thread(() -> { openCase(caseMetadataFilePath); @@ -538,8 +549,7 @@ public class MultiUserCasesPanel extends javax.swing.JPanel { 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()); + COLUMN_HEADERS.OUTPUTFOLDER.ordinal())); openCase(caseMetadataFilePath); } }//GEN-LAST:event_casesTableMouseClicked diff --git a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java index df63b0fa1f..dfcad8e516 100755 --- a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java +++ b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014 Basis Technology Corp. + * Copyright 2014-2017 Basis Technology Corp. * Contact: carrier sleuthkit 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; @@ -77,7 +76,6 @@ public final class UserPreferences { STANDALONE, AUTOINGEST, - REVIEW }; /** @@ -88,6 +86,14 @@ public final class UserPreferences { public static SelectedMode getMode() { if (ModuleSettings.settingExists(SETTINGS_PROPERTIES, MODE)) { int ordinal = Integer.parseInt(ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, MODE)); + + // If mode is 'REVIEW' (2, now invalid), set it to 'STANDALONE' (0). + if(ordinal > 1) { + setMode(SelectedMode.STANDALONE); + ModuleSettings.setConfigSetting(UserPreferences.SETTINGS_PROPERTIES, "JoinAutoModeCluster", Boolean.toString(false)); + ordinal = 0; + } + return UserPreferences.SelectedMode.values()[ordinal]; } return UserPreferences.SelectedMode.STANDALONE; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseOpenAction.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseOpenAction.java index 265190663e..6a84946c91 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseOpenAction.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseOpenAction.java @@ -53,7 +53,6 @@ final class AutoIngestCaseOpenAction extends CallableSystemAction implements Act break; case STANDALONE: - case REVIEW: /** * In standalone mode, invoke default Autopsy version of CaseOpenAction. */ diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboardOpenAction.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboardOpenAction.java index 10ff60da2a..45563a4f4b 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboardOpenAction.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboardOpenAction.java @@ -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") diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CaseImportPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CaseImportPanel.java index a7cd13af72..2e4866b010 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CaseImportPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CaseImportPanel.java @@ -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() From 2082928e514001878543a1b92c4fd8deffbb827b Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Thu, 26 Oct 2017 16:24:57 -0400 Subject: [PATCH 18/69] Moved config update logic. --- .../sleuthkit/autopsy/core/UserPreferences.java | 8 -------- .../autopsy/corecomponents/Installer.java | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java index dfcad8e516..0e7fc3da5e 100755 --- a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java +++ b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java @@ -86,14 +86,6 @@ public final class UserPreferences { public static SelectedMode getMode() { if (ModuleSettings.settingExists(SETTINGS_PROPERTIES, MODE)) { int ordinal = Integer.parseInt(ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, MODE)); - - // If mode is 'REVIEW' (2, now invalid), set it to 'STANDALONE' (0). - if(ordinal > 1) { - setMode(SelectedMode.STANDALONE); - ModuleSettings.setConfigSetting(UserPreferences.SETTINGS_PROPERTIES, "JoinAutoModeCluster", Boolean.toString(false)); - ordinal = 0; - } - return UserPreferences.SelectedMode.values()[ordinal]; } return UserPreferences.SelectedMode.STANDALONE; diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java b/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java index c908f3b35d..3f92a97760 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java @@ -30,7 +30,11 @@ import org.netbeans.swing.tabcontrol.plaf.DefaultTabbedContainerUI; import org.openide.modules.ModuleInstall; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.StartupWindowProvider; +import org.sleuthkit.autopsy.core.UserPreferences; +import static org.sleuthkit.autopsy.core.UserPreferences.SETTINGS_PROPERTIES; +import static org.sleuthkit.autopsy.core.UserPreferences.setMode; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.ModuleSettings; /** * Manages this module's life cycle. Opens the startup dialog during startup. @@ -59,6 +63,7 @@ public class Installer extends ModuleInstall { UIManager.put("ViewTabDisplayerUI", "org.sleuthkit.autopsy.corecomponents.NoTabsTabDisplayerUI"); UIManager.put(DefaultTabbedContainerUI.KEY_VIEW_CONTENT_BORDER, BorderFactory.createEmptyBorder()); UIManager.put("TabbedPane.contentBorderInsets", new Insets(0, 0, 0, 0)); + updateConfig(); WindowManager.getDefault().invokeWhenUIReady(() -> { StartupWindowProvider.getInstance().open(); }); @@ -68,6 +73,16 @@ public class Installer extends ModuleInstall { public void uninstalled() { super.uninstalled(); } + + private void updateConfig() { + // If mode is 'REVIEW' (2, now invalid), set it to 'STANDALONE' (0). + int ordinal = Integer.parseInt(ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, "AutopsyMode")); + if(ordinal > 1) { + setMode(UserPreferences.SelectedMode.STANDALONE); + ModuleSettings.setConfigSetting(UserPreferences.SETTINGS_PROPERTIES, "JoinAutoModeCluster", Boolean.toString(false)); + ordinal = 0; + } + } private void setLookAndFeel() { if (System.getProperty("os.name").toLowerCase().contains("mac")) { //NON-NLS From ad0fe641a72e9a74c0f67a65c0e7826724d6b64f Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 27 Oct 2017 12:23:22 -0400 Subject: [PATCH 19/69] Auto refresh fixed for multi-user cases panel. --- .../casemodule/CaseOpenMultiUserAction.java | 21 +---- .../autopsy/casemodule/CueBannerPanel.java | 17 +--- .../casemodule/MultiUserCasesDialog.java | 81 ++++++++++++++++++ .../casemodule/MultiUserCasesPanel.java | 84 +++++++++++-------- .../autopsy/corecomponents/Installer.java | 18 ++-- 5 files changed, 141 insertions(+), 80 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesDialog.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java index 96892cbb4e..76607210c5 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java @@ -55,25 +55,6 @@ public final class CaseOpenMultiUserAction extends CallableSystemAction implemen private static final String REVIEW_MODE_TITLE = "Open Multi-User Case (" + LOCAL_HOST_NAME + ")"; public CaseOpenMultiUserAction() {} - - /** - * Constructs the Multi-User Cases window used by the Open Multi-User Case - * menu item. - */ - private void initMultiUserCasesWindow() { - multiUserCaseWindow = new JDialog( - WindowManager.getDefault().getMainWindow(), - REVIEW_MODE_TITLE, - Dialog.ModalityType.APPLICATION_MODAL); - multiUserCaseWindow.getRootPane().registerKeyboardAction( - e -> { - multiUserCaseWindow.setVisible(false); - }, - KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW); - multiUserCaseWindow.add(MultiUserCasesPanel.getInstance()); - multiUserCaseWindow.pack(); - multiUserCaseWindow.setResizable(false); - } public static void closeMultiUserCasesWindow() { if (null != multiUserCaseWindow) { @@ -95,7 +76,7 @@ public final class CaseOpenMultiUserAction extends CallableSystemAction implemen @Override public void actionPerformed(ActionEvent event) { if(multiUserCaseWindow == null) { - initMultiUserCasesWindow(); + multiUserCaseWindow = MultiUserCasesDialog.getInstance(); } multiUserCaseWindow.setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); multiUserCaseWindow.setVisible(true); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java index 7a1c32db85..c4c15fdd91 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java @@ -113,21 +113,6 @@ public class CueBannerPanel extends javax.swing.JPanel { recentCasesWindow.pack(); recentCasesWindow.setResizable(false); } - - private void initMultiUserCasesWindow() { - multiUserCaseWindow = new JDialog( - WindowManager.getDefault().getMainWindow(), - REVIEW_MODE_TITLE, - Dialog.ModalityType.APPLICATION_MODAL); - multiUserCaseWindow.getRootPane().registerKeyboardAction( - e -> { - multiUserCaseWindow.setVisible(false); - }, - KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW); - multiUserCaseWindow.add(MultiUserCasesPanel.getInstance()); - multiUserCaseWindow.pack(); - multiUserCaseWindow.setResizable(false); - } private void enableComponents() { boolean enableOpenRecentCaseButton = (RecentCases.getInstance().getTotalRecentCases() > 0); @@ -304,7 +289,7 @@ public class CueBannerPanel extends javax.swing.JPanel { private void openMultiUserCaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openMultiUserCaseButtonActionPerformed if(multiUserCaseWindow == null) { - initMultiUserCasesWindow(); + multiUserCaseWindow = MultiUserCasesDialog.getInstance(); } multiUserCaseWindow.setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); multiUserCaseWindow.setVisible(true); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesDialog.java new file mode 100755 index 0000000000..b6d9feeb7e --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesDialog.java @@ -0,0 +1,81 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2017 Basis Technology Corp. + * Contact: carrier sleuthkit 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. + */ +public class MultiUserCasesDialog extends JDialog { + private static final String REVIEW_MODE_TITLE = "Open Multi-User Case"; + private final 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(); + } + return instance; + } + + /** + * Constructs a MultiUserCasesDialog object. + */ + MultiUserCasesDialog() { + super(WindowManager.getDefault().getMainWindow(), + REVIEW_MODE_TITLE, + Dialog.ModalityType.APPLICATION_MODAL); + + getRootPane().registerKeyboardAction( + e -> { + setVisible(false); + }, + KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW); + + multiUserCasesPanel = new MultiUserCasesPanel(); + 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.refreshCasesTable(); + } + super.setVisible(value); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java index aa2f199967..d905f36c2c 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java @@ -20,13 +20,16 @@ package org.sleuthkit.autopsy.casemodule; import java.awt.Cursor; import java.awt.Desktop; +import java.awt.EventQueue; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Date; import java.util.List; +import java.util.concurrent.ExecutionException; import java.util.logging.Level; import javax.swing.JOptionPane; +import javax.swing.SwingWorker; import javax.swing.event.ListSelectionEvent; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableColumn; @@ -79,26 +82,12 @@ public class MultiUserCasesPanel extends javax.swing.JPanel { private final String[] columnNames = {CASE_HEADER, CREATEDTIME_HEADER, COMPLETEDTIME_HEADER, STATUS_ICON_HEADER, OUTPUT_FOLDER_HEADER}; private DefaultTableModel caseTableModel; private Path currentlySelectedCase = null; - private static MultiUserCasesPanel instance; - - /* - * Gets the singleton instance of the panel. - */ - static MultiUserCasesPanel getInstance() { - if (instance == null) { - instance = new MultiUserCasesPanel(); - } - instance.refreshCasesTable(); - return instance; - } /** * Constructs a panel that allows a user to open cases created by automated * ingest. - * - * @param parent The parent dialog for this panel. */ - private MultiUserCasesPanel() { + MultiUserCasesPanel() { caseTableModel = new DefaultTableModel(columnNames, 0) { private static final long serialVersionUID = 1L; @@ -164,36 +153,57 @@ public class MultiUserCasesPanel extends javax.swing.JPanel { } setButtons(); }); - refreshCasesTable(); } /** * Gets the list of cases known to the review mode cases manager and * refreshes the cases table. */ - private void refreshCasesTable() { - try { - currentlySelectedCase = getSelectedCase(); - MultiUserCaseManager manager = MultiUserCaseManager.getInstance(); - List 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.getCaseName(), - autoIngestCase.getCreationDate(), - autoIngestCase.getLastAccessedDate(), - (MultiUserCase.CaseStatus.OK != autoIngestCase.getStatus()), - autoIngestCase.getMetadataFilePath().toString()}); + void refreshCasesTable() { + EventQueue.invokeLater(() -> { + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + }); + + new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { + try { + currentlySelectedCase = getSelectedCase(); + MultiUserCaseManager manager = MultiUserCaseManager.getInstance(); + List 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.getCaseName(), + autoIngestCase.getCreationDate(), + autoIngestCase.getLastAccessedDate(), + (MultiUserCase.CaseStatus.OK != autoIngestCase.getStatus()), + autoIngestCase.getMetadataFilePath().toString()}); + } + } + setSelectedCase(currentlySelectedCase); + setButtons(); + } catch (Exception ex) { + LOGGER.log(Level.SEVERE, "Unexpected exception while refreshing the table.", ex); //NON-NLS + } + return null; + } + + @Override + protected void done() { + super.done(); + setCursor(null); + try { + get(); + } catch (InterruptedException | ExecutionException ex) { + LOGGER.log(Level.SEVERE, "Unexpected exception while refreshing the table.", ex); //NON-NLS } } - setSelectedCase(currentlySelectedCase); - setButtons(); - } catch (Exception ex) { - LOGGER.log(Level.SEVERE, "Unexpected exception in refreshCasesTable", ex); //NON-NLS - } + }.execute(); } /** diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java b/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java index 3f92a97760..060061e205 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java @@ -32,7 +32,6 @@ import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.StartupWindowProvider; import org.sleuthkit.autopsy.core.UserPreferences; import static org.sleuthkit.autopsy.core.UserPreferences.SETTINGS_PROPERTIES; -import static org.sleuthkit.autopsy.core.UserPreferences.setMode; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ModuleSettings; @@ -74,13 +73,18 @@ public class Installer extends ModuleInstall { super.uninstalled(); } + /** + * 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() { - // If mode is 'REVIEW' (2, now invalid), set it to 'STANDALONE' (0). - int ordinal = Integer.parseInt(ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, "AutopsyMode")); - if(ordinal > 1) { - setMode(UserPreferences.SelectedMode.STANDALONE); - ModuleSettings.setConfigSetting(UserPreferences.SETTINGS_PROPERTIES, "JoinAutoModeCluster", Boolean.toString(false)); - ordinal = 0; + 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)); + } } } From 13f16c417de559662561418861ab87863d315f2d Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 27 Oct 2017 13:44:28 -0400 Subject: [PATCH 20/69] 3153 - sort Priority column in descending order --- .../experimental/autoingest/AutoIngestControlPanel.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index 26dcabff58..25b29e3665 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -1862,8 +1862,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { @Override public void toggleSortOrder(int column) { - if (!this.getModel().getColumnClass(column).equals(Date.class)) { - super.toggleSortOrder(column); //if it isn't a date perform the regular sorting + if (!this.getModel().getColumnClass(column).equals(Date.class) && !(this.getModel().getColumnName(column).equals(JobsTableModelColumns.PRIORITY.getColumnHeader()))) { + super.toggleSortOrder(column); //if it isn't a date or the Priority column perform the regular sorting } else { ArrayList sortKeys = new ArrayList<>(getSortKeys()); if (sortKeys.isEmpty() || sortKeys.get(0).getColumn() != column) { //sort descending From d480a08bf100443f102f60946336c4ea5b7fa8bf Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Tue, 31 Oct 2017 16:32:21 -0400 Subject: [PATCH 21/69] Removal of examiner mode. --- .../AutoIngestCasePanelInterface.java | 29 - .../autopsy/casemodule/Bundle.properties | 33 +- .../autopsy/casemodule/Bundle_ja.properties | 9 +- .../autopsy/casemodule/CaseDeleteAction.java | 3 +- .../autopsy/casemodule/CaseOpenAction.java | 2 +- .../casemodule/CaseOpenMultiUserAction.java | 104 +++ .../autopsy/casemodule/CueBannerPanel.form | 20 +- .../autopsy/casemodule/CueBannerPanel.java | 94 +- .../autopsy/casemodule/MultiUserCase.java | 286 ++++++ .../casemodule/MultiUserCaseManager.java | 136 +++ .../casemodule/MultiUserCasesDialog.java | 81 ++ .../casemodule/MultiUserCasesPanel.form | 20 +- .../casemodule/MultiUserCasesPanel.java | 407 ++++---- .../autopsy/core/UserPreferences.java | 6 +- Core/src/org/sleuthkit/autopsy/core/layer.xml | 8 +- .../autopsy/corecomponents/Installer.java | 19 + .../CaseStatusIconCellRenderer.java | 11 +- .../coreutils}/GrayableCellRenderer.java | 8 +- .../coreutils}/LongDateCellRenderer.java | 6 +- .../autopsy/coreutils}/TimeStampUtils.java | 4 +- .../autoingest/AddArchiveTask.java | 1 + .../autoingest/AutoIngestCase.java | 189 ---- .../autoingest/AutoIngestCaseManager.java | 162 ---- .../autoingest/AutoIngestCaseOpenAction.java | 99 -- .../autoingest/AutoIngestControlPanel.java | 2 + .../autoingest/AutoIngestDashboard.java | 2 + .../AutoIngestDashboardOpenAction.java | 4 +- .../autoingest/AutoIngestManager.java | 4 +- .../experimental/autoingest/Bundle.properties | 11 +- .../autoingest/CaseImportPanel.java | 1 - .../CenteredGrayableCellRenderer.java | 3 +- .../autoingest/DurationCellRenderer.java | 24 + .../experimental/autoingest/PathUtils.java | 1 + .../autoingest/ShortDateCellRenderer.java | 24 + .../autoingest/SingleUserCaseImporter.java | 1 + .../AutoIngestSettingsPanel.form | 884 +++++++----------- .../AutoIngestSettingsPanel.java | 745 ++++++--------- .../configuration/Bundle.properties | 29 +- 38 files changed, 1589 insertions(+), 1883 deletions(-) delete mode 100755 Core/src/org/sleuthkit/autopsy/casemodule/AutoIngestCasePanelInterface.java create mode 100755 Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java create mode 100755 Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java create mode 100755 Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java create mode 100755 Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesDialog.java rename Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.form => Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form (84%) rename Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java => Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java (64%) rename {Experimental/src/org/sleuthkit/autopsy/experimental/autoingest => Core/src/org/sleuthkit/autopsy/coreutils}/CaseStatusIconCellRenderer.java (82%) rename {Experimental/src/org/sleuthkit/autopsy/experimental/autoingest => Core/src/org/sleuthkit/autopsy/coreutils}/GrayableCellRenderer.java (91%) rename {Experimental/src/org/sleuthkit/autopsy/experimental/autoingest => Core/src/org/sleuthkit/autopsy/coreutils}/LongDateCellRenderer.java (91%) rename {Experimental/src/org/sleuthkit/autopsy/experimental/autoingest => Core/src/org/sleuthkit/autopsy/coreutils}/TimeStampUtils.java (97%) delete mode 100755 Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCase.java delete mode 100755 Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseManager.java delete mode 100755 Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseOpenAction.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AutoIngestCasePanelInterface.java b/Core/src/org/sleuthkit/autopsy/casemodule/AutoIngestCasePanelInterface.java deleted file mode 100755 index 795b636b35..0000000000 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AutoIngestCasePanelInterface.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011-2017 Basis Technology Corp. - * Contact: carrier sleuthkit 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); -} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index 25b43a423a..5b80fd80ba 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -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_OpenAction=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 \ No newline at end of file +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 diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties index e212a125e9..de333e790f 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties @@ -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 diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseDeleteAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseDeleteAction.java index 3ef30f2594..b95ad78edf 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseDeleteAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseDeleteAction.java @@ -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; /** @@ -51,7 +50,7 @@ final class CaseDeleteAction extends CallableSystemAction { 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); + setEnabled(null != evt.getNewValue()); }); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java index 533cab58c5..e4ed92d897 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java @@ -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 diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java new file mode 100755 index 0000000000..76607210c5 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java @@ -0,0 +1,104 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2017 Basis Technology Corp. + * Contact: carrier sleuthkit 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.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.KeyStroke; +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; +import org.sleuthkit.autopsy.coreutils.NetworkUtils; + +/** + * 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(); + private static final String LOCAL_HOST_NAME = NetworkUtils.getLocalHostName(); + private static final String REVIEW_MODE_TITLE = "Open Multi-User Case (" + LOCAL_HOST_NAME + ")"; + + public CaseOpenMultiUserAction() {} + + public static void closeMultiUserCasesWindow() { + if (null != multiUserCaseWindow) { + multiUserCaseWindow.setVisible(false); + } + } + + @Override + public boolean isEnabled() { + return UserPreferences.getIsMultiUserModeEnabled(); + } + + /** + * Pops up a case selection panel to allow the user to selecte a multi-user + * case to open. + * + * @param e 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 + } +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.form index 75819e41d0..0d6525db8b 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.form @@ -28,14 +28,14 @@ - + - + @@ -66,9 +66,9 @@ - + - + @@ -216,13 +216,13 @@ - + - + @@ -237,18 +237,18 @@ - + - + - + - + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java index 2d7b17458e..c4c15fdd91 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java @@ -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,13 @@ 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 + ")"; + private static final String REVIEW_MODE_TITLE = "Open Multi-User Case"; /* * This is field is static for the sake of the closeOpenRecentCasesWindow * method. */ private static JDialog recentCasesWindow; - private static JDialog autoIngestCasePanelWindow; + private static JDialog multiUserCaseWindow; public static void closeOpenRecentCasesWindow() { if (null != recentCasesWindow) { @@ -56,9 +52,9 @@ public class CueBannerPanel extends javax.swing.JPanel { } } - public static void closeAutoIngestCasesWindow() { - if (null != autoIngestCasePanelWindow) { - autoIngestCasePanelWindow.setVisible(false); + public static void closeMultiUserCasesWindow() { + if (null != multiUserCaseWindow) { + multiUserCaseWindow.setVisible(false); } } @@ -93,7 +89,6 @@ public class CueBannerPanel extends javax.swing.JPanel { private void customizeComponents() { initRecentCasesWindow(); - initAutoIngestCasesWindow(); } private void initRecentCasesWindow() { @@ -118,39 +113,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 +143,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 +200,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 +232,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 +261,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 +287,13 @@ 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 + if(multiUserCaseWindow == null) { + 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 +301,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; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java new file mode 100755 index 0000000000..502ff260b1 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java @@ -0,0 +1,286 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2015-2017 Basis Technology Corp. + * Contact: carrier sleuthkit 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.Comparator; +import java.util.Date; +import java.util.Objects; +import java.util.logging.Level; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.TimeStampUtils; + +/** + * A representation of a case created by automated ingest. + */ +class MultiUserCase implements Comparable { + + private static final Logger logger = Logger.getLogger(MultiUserCase.class.getName()); + private final Path caseDirectoryPath; + private final String caseDisplayName; + private final String metadataFileName; + private final Date createDate; + private final Date lastAccessedDate; + + /** + * Constructs a representation of case created by automated ingest. + * + * @param caseDirectoryPath The case directory path. + * + * @throws CaseMetadata.CaseMetadataException If the CaseMetadata object + * cannot be constructed for the + * case display name. + * @throws MultiUserCaseException If no case metadata (.aut) + * file is found in the case + * directory. + */ + MultiUserCase(Path caseDirectoryPath) throws CaseMetadata.CaseMetadataException, MultiUserCaseException { + CaseMetadata caseMetadata = null; + + try { + caseMetadata = getCaseMetadataFromCaseDirectoryPath(caseDirectoryPath); + } catch (CaseMetadata.CaseMetadataException ex) { + logger.log(Level.SEVERE, String.format("Error reading the case metadata for %s.", caseDirectoryPath), ex); + throw ex; + } + + this.caseDirectoryPath = caseDirectoryPath; + caseDisplayName = caseMetadata.getCaseDisplayName(); + metadataFileName = caseMetadata.getFilePath().getFileName().toString(); + 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 based on the auto ingest result file in the + * case directory. + * + * @return See CaseStatus enum definition. + */ + CaseStatus getStatus() { + if(caseDirectoryPath.resolve("autoingest.alert").toFile().exists()) { + return CaseStatus.ALERT; + } else { + return CaseStatus.OK; + } + } + + /** + * 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 static 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 AutopIngestCase object with abnother 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 { + + /** + * Compares two MultiUserCase objects for order based on last accessed + * date (descending). + * + * @param object The first MultiUserCase 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(MultiUserCase object, MultiUserCase otherObject) { + return -object.getLastAccessedDate().compareTo(otherObject.getLastAccessedDate()); + } + } + + /** + * Exception thrown when there is a problem creating a multi-user case. + */ + final static 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); + } + } + + enum CaseStatus { + + OK, + ALERT + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java new file mode 100755 index 0000000000..3101461443 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java @@ -0,0 +1,136 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2017 Basis Technology Corp. + * Contact: carrier sleuthkit 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.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import org.sleuthkit.autopsy.coordinationservice.CoordinationService; +import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; + +/** + * Handles locating and opening multi-user cases. + */ +final class MultiUserCaseManager { + + 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 getCases() throws CoordinationServiceException { + List cases = new ArrayList<>(); + List nodeList = coordinationService.getNodeList(CoordinationService.CategoryNode.CASES); + for (String node : nodeList) { + Path casePath = Paths.get(node); + File caseFolder = casePath.toFile(); + if(caseFolder.exists()) { + File[] autFiles = caseFolder.listFiles((dir, name) -> name.toLowerCase().endsWith(".aut")); + if(autFiles != null && autFiles.length > 0) { + try { + cases.add(new MultiUserCase(casePath)); + } catch (CaseMetadata.CaseMetadataException | MultiUserCase.MultiUserCaseException ex) { + // Ignore and continue. + } + } + } + } + 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); + } + + } +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesDialog.java new file mode 100755 index 0000000000..b6d9feeb7e --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesDialog.java @@ -0,0 +1,81 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2017 Basis Technology Corp. + * Contact: carrier sleuthkit 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. + */ +public class MultiUserCasesDialog extends JDialog { + private static final String REVIEW_MODE_TITLE = "Open Multi-User Case"; + private final 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(); + } + return instance; + } + + /** + * Constructs a MultiUserCasesDialog object. + */ + MultiUserCasesDialog() { + super(WindowManager.getDefault().getMainWindow(), + REVIEW_MODE_TITLE, + Dialog.ModalityType.APPLICATION_MODAL); + + getRootPane().registerKeyboardAction( + e -> { + setVisible(false); + }, + KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW); + + multiUserCasesPanel = new MultiUserCasesPanel(); + 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.refreshCasesTable(); + } + super.setVisible(value); + } +} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form similarity index 84% rename from Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.form rename to Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form index cb0f275809..179bc23bb8 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form @@ -45,7 +45,7 @@ - + @@ -82,7 +82,7 @@ - + @@ -118,7 +118,7 @@ - + @@ -153,7 +153,7 @@ - + @@ -165,10 +165,10 @@ - + - + @@ -182,7 +182,7 @@ - + @@ -196,7 +196,7 @@ - + @@ -209,7 +209,7 @@ - + @@ -222,7 +222,7 @@ - + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java similarity index 64% rename from Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java rename to Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java index 2bcd335916..bce0a33602 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java @@ -16,52 +16,38 @@ * 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.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.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 org.sleuthkit.autopsy.coreutils.CaseStatusIconCellRenderer; +import org.sleuthkit.autopsy.coreutils.GrayableCellRenderer; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.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; /** * 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 { +public 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 MultiUserCase.LastAccessedDateDescendingComparator REVERSE_DATE_MODIFIED_COMPARATOR = new 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 +57,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 +65,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 +78,18 @@ 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(); - } - }); - } /** * 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() { caseTableModel = new DefaultTableModel(columnNames, 0) { private static final long serialVersionUID = 1L; @@ -146,6 +97,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)) { @@ -191,6 +143,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP theColumn.setWidth(STATUS_COL_PREFERRED_WIDTH); casesTable.removeColumn(casesTable.getColumn(OUTPUT_FOLDER_HEADER)); + casesTable.removeColumn(casesTable.getColumn(METADATA_FILE_HEADER)); /* * Listen for row selection changes and set button state for the current @@ -203,76 +156,58 @@ 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() { - try { - currentlySelectedCase = getSelectedCase(); - AutoIngestCaseManager manager = AutoIngestCaseManager.getInstance(); - List theModel = manager.getCases(); - EventQueue.invokeLater(new CaseTableRefreshTask(theModel)); - } catch (Exception ex) { - logger.log(Level.SEVERE, "Unexpected exception in refreshCasesTable", ex); //NON-NLS - } + void refreshCasesTable() { + EventQueue.invokeLater(() -> { + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + }); + + new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { + try { + currentlySelectedCase = getSelectedCase(); + MultiUserCaseManager manager = MultiUserCaseManager.getInstance(); + List 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(), + (MultiUserCase.CaseStatus.OK != autoIngestCase.getStatus()), + autoIngestCase.getCaseDirectoryPath().toString(), + autoIngestCase.getMetadataFileName()}); + } + } + setSelectedCase(currentlySelectedCase); + setButtons(); + } catch (Exception ex) { + LOGGER.log(Level.SEVERE, "Unexpected exception while refreshing the table.", ex); //NON-NLS + } + return null; + } + + @Override + protected void done() { + super.done(); + setCursor(null); + try { + get(); + } catch (InterruptedException | ExecutionException ex) { + LOGGER.log(Level.SEVERE, "Unexpected exception while refreshing the table.", ex); //NON-NLS + } + } + }.execute(); } /** @@ -320,9 +255,30 @@ 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); + } + + /** + * 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; } /** @@ -332,91 +288,44 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP */ private void openCase(Path caseMetadataFilePath) { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - new SwingWorker() { - - @Override - protected Void doInBackground() throws Exception { - AutoIngestCaseManager.getInstance().openCase(caseMetadataFilePath); - stopCasesTableRefreshes(); - StartupWindowProvider.getInstance().close(); - CueBannerPanel.closeAutoIngestCasesWindow(); - return null; + try { + StartupWindowProvider.getInstance().close(); + CueBannerPanel.closeMultiUserCasesWindow(); + CaseOpenMultiUserAction.closeMultiUserCasesWindow(); + 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()); } - - @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)); - } - } - }.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 final List cases; - - CaseTableRefreshTask(List cases) { - setButtons(); - this.cases = cases; + 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; } - - /** - * @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()}); - } - } - 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); - } - + return ((currentTime - inputTime) / (1000 * 60 * 60 * 24)) < (numberOfUnits * multiplier); } /** @@ -443,7 +352,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) { @@ -463,7 +372,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 +381,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 +403,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 +413,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 +422,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 +430,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 +438,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 +465,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 +497,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 +510,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) { + refreshCasesTable(); + } - private void rbDaysItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbDaysItemStateChanged + private void rbDaysItemStateChanged(java.awt.event.ItemEvent evt) { if (rbDays.isSelected()) { - updateView(); + refreshCasesTable(); } - }//GEN-LAST:event_rbDaysItemStateChanged + } private void rbAllCasesItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbAllCasesItemStateChanged if (rbAllCases.isSelected()) { - updateView(); + refreshCasesTable(); } }//GEN-LAST:event_rbAllCasesItemStateChanged private void rbMonthsItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbMonthsItemStateChanged if (rbMonths.isSelected()) { - updateView(); + refreshCasesTable(); } }//GEN-LAST:event_rbMonthsItemStateChanged private void rbWeeksItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbWeeksItemStateChanged if (rbWeeks.isSelected()) { - updateView(); + refreshCasesTable(); } }//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 +562,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 diff --git a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java index df63b0fa1f..86f68e1df5 100755 --- a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java +++ b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014 Basis Technology Corp. + * Copyright 2014-2017 Basis Technology Corp. * Contact: carrier sleuthkit 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 }; /** diff --git a/Core/src/org/sleuthkit/autopsy/core/layer.xml b/Core/src/org/sleuthkit/autopsy/core/layer.xml index 95cfcd481e..fb5618c6e6 100755 --- a/Core/src/org/sleuthkit/autopsy/core/layer.xml +++ b/Core/src/org/sleuthkit/autopsy/core/layer.xml @@ -51,7 +51,7 @@ - + @@ -157,7 +157,7 @@ - + @@ -165,11 +165,11 @@ - + - + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java b/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java index c908f3b35d..060061e205 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java @@ -30,7 +30,10 @@ import org.netbeans.swing.tabcontrol.plaf.DefaultTabbedContainerUI; import org.openide.modules.ModuleInstall; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.StartupWindowProvider; +import org.sleuthkit.autopsy.core.UserPreferences; +import static org.sleuthkit.autopsy.core.UserPreferences.SETTINGS_PROPERTIES; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.ModuleSettings; /** * Manages this module's life cycle. Opens the startup dialog during startup. @@ -59,6 +62,7 @@ public class Installer extends ModuleInstall { UIManager.put("ViewTabDisplayerUI", "org.sleuthkit.autopsy.corecomponents.NoTabsTabDisplayerUI"); UIManager.put(DefaultTabbedContainerUI.KEY_VIEW_CONTENT_BORDER, BorderFactory.createEmptyBorder()); UIManager.put("TabbedPane.contentBorderInsets", new Insets(0, 0, 0, 0)); + updateConfig(); WindowManager.getDefault().invokeWhenUIReady(() -> { StartupWindowProvider.getInstance().open(); }); @@ -68,6 +72,21 @@ public class Installer extends ModuleInstall { public void uninstalled() { super.uninstalled(); } + + /** + * 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)); + } + } + } private void setLookAndFeel() { if (System.getProperty("os.name").toLowerCase().contains("mac")) { //NON-NLS diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CaseStatusIconCellRenderer.java b/Core/src/org/sleuthkit/autopsy/coreutils/CaseStatusIconCellRenderer.java similarity index 82% rename from Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CaseStatusIconCellRenderer.java rename to Core/src/org/sleuthkit/autopsy/coreutils/CaseStatusIconCellRenderer.java index 0010cc90ee..4d782a6f57 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CaseStatusIconCellRenderer.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/CaseStatusIconCellRenderer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015 Basis Technology Corp. + * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,24 +16,29 @@ * 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.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 an auto ingest alert file exists flag * as a center-aligned icon, and grays out the cell if the table is disabled. */ -class CaseStatusIconCellRenderer extends GrayableCellRenderer { +public class CaseStatusIconCellRenderer extends GrayableCellRenderer { 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)); + @Messages({ + "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" + }) @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { setHorizontalAlignment(CENTER); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/GrayableCellRenderer.java b/Core/src/org/sleuthkit/autopsy/coreutils/GrayableCellRenderer.java similarity index 91% rename from Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/GrayableCellRenderer.java rename to Core/src/org/sleuthkit/autopsy/coreutils/GrayableCellRenderer.java index 60d3b77ccd..479f30bee2 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/GrayableCellRenderer.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/GrayableCellRenderer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015 Basis Technology Corp. + * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit 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.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); } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/LongDateCellRenderer.java b/Core/src/org/sleuthkit/autopsy/coreutils/LongDateCellRenderer.java similarity index 91% rename from Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/LongDateCellRenderer.java rename to Core/src/org/sleuthkit/autopsy/coreutils/LongDateCellRenderer.java index cfa2cedb14..e347b2d28a 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/LongDateCellRenderer.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/LongDateCellRenderer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015 Basis Technology Corp. + * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit 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.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 diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/TimeStampUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/TimeStampUtils.java similarity index 97% rename from Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/TimeStampUtils.java rename to Core/src/org/sleuthkit/autopsy/coreutils/TimeStampUtils.java index fe53871dd5..4b22a6010d 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/TimeStampUtils.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/TimeStampUtils.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015 Basis Technology Corp. + * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit 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; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AddArchiveTask.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AddArchiveTask.java index 3bc76e61fd..b2204f1b2c 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AddArchiveTask.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AddArchiveTask.java @@ -28,6 +28,7 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.TimeStampUtils; import org.sleuthkit.datamodel.Content; /* diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCase.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCase.java deleted file mode 100755 index ff47423030..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCase.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2015-2017 Basis Technology Corp. - * Contact: carrier sleuthkit 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 { - - 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 { - - /** - * 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 - } - -} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseManager.java deleted file mode 100755 index 8469ff2315..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseManager.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011-2017 Basis Technology Corp. - * Contact: carrier sleuthkit 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 getCases() throws AutoIngestCaseManagerException { - List cases = new ArrayList<>(); - List 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 getCasePaths() throws AutoIngestCaseManagerException { - try { - List nodeList = coordinationService.getNodeList(CoordinationService.CategoryNode.CASES); - List casePathList = new ArrayList(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); - } - - } -} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseOpenAction.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseOpenAction.java deleted file mode 100755 index e86a7bcf8a..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseOpenAction.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2015 Basis Technology Corp. - * Contact: carrier sleuthkit 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; - } - -} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index 891975223a..de737978cb 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -57,6 +57,8 @@ import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.core.ServicesMonitor; +import org.sleuthkit.autopsy.coreutils.CaseStatusIconCellRenderer; +import org.sleuthkit.autopsy.coreutils.LongDateCellRenderer; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.NetworkUtils; import org.sleuthkit.autopsy.coreutils.PlatformUtil; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java index 2d10dff258..5537d07236 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java @@ -41,7 +41,9 @@ import javax.swing.table.TableColumn; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.core.ServicesMonitor; +import org.sleuthkit.autopsy.coreutils.CaseStatusIconCellRenderer; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.LongDateCellRenderer; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestMonitor.JobsSnapshot; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboardOpenAction.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboardOpenAction.java index 7e1b1907af..45563a4f4b 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboardOpenAction.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboardOpenAction.java @@ -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 diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index 2f2f22fb0d..0c6c39e0b1 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -62,6 +62,7 @@ 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.CoordinationService; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; @@ -2115,7 +2116,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 diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties index edac418672..7b6a28a9f3 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties @@ -1,4 +1,4 @@ -CTL_OpenAction=Open Case... +CTL_OpenAction=Open Case AutoIngestDashboard.lbCompleted.text=Completed Jobs AutoIngestDashboard.lbRunning.text=Running Jobs AutoIngestDashboard.lbPending.text=Pending Jobs @@ -231,15 +231,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 diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CaseImportPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CaseImportPanel.java index a7cd13af72..2e4866b010 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CaseImportPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CaseImportPanel.java @@ -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() diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CenteredGrayableCellRenderer.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CenteredGrayableCellRenderer.java index b9040b674b..04422cd63a 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CenteredGrayableCellRenderer.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CenteredGrayableCellRenderer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015 Basis Technology Corp. + * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.experimental.autoingest; import static javax.swing.SwingConstants.CENTER; +import org.sleuthkit.autopsy.coreutils.GrayableCellRenderer; /** * A JTable cell renderer that center-aligns cell content and grays out the cell diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/DurationCellRenderer.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/DurationCellRenderer.java index 6bac0a996b..c61e363222 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/DurationCellRenderer.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/DurationCellRenderer.java @@ -18,10 +18,12 @@ */ package org.sleuthkit.autopsy.experimental.autoingest; +import java.awt.Color; import java.awt.Component; import java.time.Duration; import javax.swing.JTable; import static javax.swing.SwingConstants.CENTER; +import org.sleuthkit.autopsy.coreutils.GrayableCellRenderer; /** * A JTable cell renderer that renders a duration represented as a long as a @@ -71,4 +73,26 @@ class DurationCellRenderer extends GrayableCellRenderer { grayCellIfTableNotEnabled(table, isSelected); return this; } + + void grayCellIfTableNotEnabled(JTable table, boolean isSelected) { + if (table.isEnabled()) { + /* + * The table is enabled, make the foreground and background the + * normal selected or unselected color. + */ + if (isSelected) { + setBackground(table.getSelectionBackground()); + setForeground(table.getSelectionForeground()); + } else { + setBackground(table.getBackground()); + setForeground(table.getForeground()); + } + } else { + /* + * The table is disabled, make the foreground and background gray. + */ + setBackground(Color.lightGray); + setForeground(Color.darkGray); + } + } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PathUtils.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PathUtils.java index 18ce9709d5..a7d5675883 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PathUtils.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PathUtils.java @@ -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 { diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ShortDateCellRenderer.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ShortDateCellRenderer.java index 713d177c0a..f2670fa1b7 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ShortDateCellRenderer.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ShortDateCellRenderer.java @@ -18,10 +18,12 @@ */ package org.sleuthkit.autopsy.experimental.autoingest; +import java.awt.Color; import java.awt.Component; import java.text.SimpleDateFormat; import javax.swing.JTable; import static javax.swing.SwingConstants.CENTER; +import org.sleuthkit.autopsy.coreutils.GrayableCellRenderer; /** * A JTable cell renderer that renders a date represented as a long as a @@ -46,4 +48,26 @@ class ShortDateCellRenderer extends GrayableCellRenderer { grayCellIfTableNotEnabled(table, isSelected); return this; } + + void grayCellIfTableNotEnabled(JTable table, boolean isSelected) { + if (table.isEnabled()) { + /* + * The table is enabled, make the foreground and background the + * normal selected or unselected color. + */ + if (isSelected) { + setBackground(table.getSelectionBackground()); + setForeground(table.getSelectionForeground()); + } else { + setBackground(table.getBackground()); + setForeground(table.getForeground()); + } + } else { + /* + * The table is disabled, make the foreground and background gray. + */ + setBackground(Color.lightGray); + setForeground(Color.darkGray); + } + } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/SingleUserCaseImporter.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/SingleUserCaseImporter.java index e04399d321..3a5c45632f 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/SingleUserCaseImporter.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/SingleUserCaseImporter.java @@ -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 { diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.form b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.form index 20c8c7a981..9965d1ad8f 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.form +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.form @@ -56,18 +56,71 @@ - - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -79,542 +132,65 @@ - - + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -649,6 +225,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.java index 4877ce9d60..892a27aab6 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.java @@ -56,7 +56,7 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel { enum OptionsUiMode { - STANDALONE, AIM, REVIEW, DOWNLOADING_CONFIGURATION + STANDALONE, AIM, DOWNLOADING_CONFIGURATION }; /** @@ -127,21 +127,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 +196,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 +213,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 +278,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; } @@ -579,24 +542,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 +569,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; } } @@ -636,289 +586,49 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel { 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 +659,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 +756,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 +814,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 +878,35 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel { ); }// //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 +943,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 +955,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 +1021,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 +1063,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 +1170,7 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel { } void setEnabledStateForSharedConfiguration() { - if (jRadioButtonAutomated.isSelected() && cbJoinAutoIngestCluster.isSelected()) { + if (cbJoinAutoIngestCluster.isSelected()) { enableOptionsBasedOnMode(OptionsUiMode.AIM); } } @@ -1361,19 +1182,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,20 +1204,12 @@ 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; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties index 66ed50dd20..a12453e3c1 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties @@ -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 From dd7c6d9c033477384a0dacee228c66482b545666 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Tue, 31 Oct 2017 16:38:11 -0400 Subject: [PATCH 22/69] Removed unnecessary method. --- .../org/sleuthkit/autopsy/casemodule/CueBannerPanel.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java index c4c15fdd91..9a45304c0f 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java @@ -60,7 +60,7 @@ public class CueBannerPanel extends javax.swing.JPanel { public CueBannerPanel() { initComponents(); - customizeComponents(); + initRecentCasesWindow(); enableComponents(); } @@ -86,10 +86,6 @@ public class CueBannerPanel extends javax.swing.JPanel { public void refresh() { enableComponents(); } - - private void customizeComponents() { - initRecentCasesWindow(); - } private void initRecentCasesWindow() { recentCasesWindow = new JDialog( From ae4f07c16461b51038fee78f942fced194197d45 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Tue, 31 Oct 2017 17:14:33 -0400 Subject: [PATCH 23/69] Updated documentation; moved updateConfig() to 'core' Installer. --- .../autopsy/casemodule/CueBannerPanel.java | 2 +- .../autopsy/casemodule/MultiUserCase.java | 9 ++++---- .../org/sleuthkit/autopsy/core/Installer.java | 22 +++++++++++++++++-- .../autopsy/corecomponents/Installer.java | 19 ---------------- 4 files changed, 25 insertions(+), 27 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java index 9a45304c0f..24c714eb5b 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java @@ -71,7 +71,7 @@ public class CueBannerPanel extends javax.swing.JPanel { ImageIcon icon = new ImageIcon(cl.getResource(welcomeLogo)); autopsyLogo.setIcon(icon); } - customizeComponents(); + initRecentCasesWindow(); enableComponents(); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java index 502ff260b1..e0bba29c43 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java @@ -29,10 +29,9 @@ import java.util.Date; import java.util.Objects; import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.TimeStampUtils; /** - * A representation of a case created by automated ingest. + * A representation of a multi-user case. */ class MultiUserCase implements Comparable { @@ -44,7 +43,7 @@ class MultiUserCase implements Comparable { private final Date lastAccessedDate; /** - * Constructs a representation of case created by automated ingest. + * Constructs a representation of a multi-user case * * @param caseDirectoryPath The case directory path. * @@ -219,7 +218,7 @@ class MultiUserCase implements Comparable { } /** - * Compares this AutopIngestCase object with abnother MultiUserCase object + * Compares this MultiUserCase object with another MultiUserCase object * for order. */ @Override @@ -237,7 +236,7 @@ class MultiUserCase implements Comparable { * date (descending). * * @param object The first MultiUserCase object - * @param otherObject The second AuotIngestCase 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. diff --git a/Core/src/org/sleuthkit/autopsy/core/Installer.java b/Core/src/org/sleuthkit/autopsy/core/Installer.java index 0b660acd2a..83250f719d 100755 --- a/Core/src/org/sleuthkit/autopsy/core/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/core/Installer.java @@ -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 diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java b/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java index 060061e205..c908f3b35d 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java @@ -30,10 +30,7 @@ import org.netbeans.swing.tabcontrol.plaf.DefaultTabbedContainerUI; import org.openide.modules.ModuleInstall; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.StartupWindowProvider; -import org.sleuthkit.autopsy.core.UserPreferences; -import static org.sleuthkit.autopsy.core.UserPreferences.SETTINGS_PROPERTIES; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.ModuleSettings; /** * Manages this module's life cycle. Opens the startup dialog during startup. @@ -62,7 +59,6 @@ public class Installer extends ModuleInstall { UIManager.put("ViewTabDisplayerUI", "org.sleuthkit.autopsy.corecomponents.NoTabsTabDisplayerUI"); UIManager.put(DefaultTabbedContainerUI.KEY_VIEW_CONTENT_BORDER, BorderFactory.createEmptyBorder()); UIManager.put("TabbedPane.contentBorderInsets", new Insets(0, 0, 0, 0)); - updateConfig(); WindowManager.getDefault().invokeWhenUIReady(() -> { StartupWindowProvider.getInstance().open(); }); @@ -72,21 +68,6 @@ public class Installer extends ModuleInstall { public void uninstalled() { super.uninstalled(); } - - /** - * 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)); - } - } - } private void setLookAndFeel() { if (System.getProperty("os.name").toLowerCase().contains("mac")) { //NON-NLS From 59df3725072497ed149410895333eb4f31e73816 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Tue, 31 Oct 2017 17:23:21 -0400 Subject: [PATCH 24/69] Add unit test utilities to Autopsy-Core NBM --- .../testutils/UnitTestDspCallback.java | 109 ++++++++++++++++++ .../testutils/UnitTestDspProgressMonitor.java | 62 ++++++++++ 2 files changed, 171 insertions(+) create mode 100755 Core/test/unit/src/org/sleuthkit/autopsy/testutils/UnitTestDspCallback.java create mode 100755 Core/test/unit/src/org/sleuthkit/autopsy/testutils/UnitTestDspProgressMonitor.java diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/testutils/UnitTestDspCallback.java b/Core/test/unit/src/org/sleuthkit/autopsy/testutils/UnitTestDspCallback.java new file mode 100755 index 0000000000..c6adb1f24c --- /dev/null +++ b/Core/test/unit/src/org/sleuthkit/autopsy/testutils/UnitTestDspCallback.java @@ -0,0 +1,109 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2017 Basis Technology Corp. + * Contact: carrier sleuthkit 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 UnitTestDspCallback extends DataSourceProcessorCallback { + + private final Object monitor; + private final List errorMessages = new ArrayList<>(); + private final List 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. + */ + UnitTestDspCallback(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 errorMessages, List 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 errorMessages, List 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 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 getDataSourceContent() { + return new ArrayList<>(this.dataSourceContent); + } + +} diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/testutils/UnitTestDspProgressMonitor.java b/Core/test/unit/src/org/sleuthkit/autopsy/testutils/UnitTestDspProgressMonitor.java new file mode 100755 index 0000000000..1f856e6500 --- /dev/null +++ b/Core/test/unit/src/org/sleuthkit/autopsy/testutils/UnitTestDspProgressMonitor.java @@ -0,0 +1,62 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2017 Basis Technology Corp. + * Contact: carrier sleuthkit 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 UnitTestDspProgressMonitor 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) { + } + +} From 2d4852f22d40d8ccbb633b4a76a4d926133a9c54 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 1 Nov 2017 09:53:45 -0400 Subject: [PATCH 25/69] Table refresh NPE fixed using 'invokeLater()'. --- .../casemodule/MultiUserCasesPanel.java | 68 ++++++++----------- 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java index bce0a33602..42201e5850 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java @@ -29,6 +29,7 @@ import java.util.List; import java.util.concurrent.ExecutionException; import java.util.logging.Level; import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import javax.swing.event.ListSelectionEvent; import javax.swing.table.DefaultTableModel; @@ -167,47 +168,38 @@ public class MultiUserCasesPanel extends javax.swing.JPanel { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); }); - new SwingWorker() { - - @Override - protected Void doInBackground() throws Exception { - try { - currentlySelectedCase = getSelectedCase(); - MultiUserCaseManager manager = MultiUserCaseManager.getInstance(); - List 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(), - (MultiUserCase.CaseStatus.OK != autoIngestCase.getStatus()), - autoIngestCase.getCaseDirectoryPath().toString(), - autoIngestCase.getMetadataFileName()}); + synchronized(this) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + try { + currentlySelectedCase = getSelectedCase(); + MultiUserCaseManager manager = MultiUserCaseManager.getInstance(); + List 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(), + (MultiUserCase.CaseStatus.OK != autoIngestCase.getStatus()), + autoIngestCase.getCaseDirectoryPath().toString(), + autoIngestCase.getMetadataFileName()}); + } } + setSelectedCase(currentlySelectedCase); + setButtons(); + } catch (Exception ex) { + LOGGER.log(Level.SEVERE, "Unexpected exception while refreshing the table.", ex); //NON-NLS + } finally { + setCursor(null); } - setSelectedCase(currentlySelectedCase); - setButtons(); - } catch (Exception ex) { - LOGGER.log(Level.SEVERE, "Unexpected exception while refreshing the table.", ex); //NON-NLS } - return null; - } - - @Override - protected void done() { - super.done(); - setCursor(null); - try { - get(); - } catch (InterruptedException | ExecutionException ex) { - LOGGER.log(Level.SEVERE, "Unexpected exception while refreshing the table.", ex); //NON-NLS - } - } - }.execute(); + }); + } } /** From a19b32e3893278034f22b9cd1b925abc45a27e2e Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 1 Nov 2017 16:25:15 -0400 Subject: [PATCH 26/69] Rewrote portions of 'doRecoveryIfCrashed()' to fix bugs. --- .../autoingest/AutoIngestManager.java | 248 +++++------------- 1 file changed, 63 insertions(+), 185 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index 9f43879b55..a779085813 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -37,7 +37,6 @@ import java.time.Duration; import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.EnumSet; @@ -59,13 +58,11 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.stream.Collectors; import javax.annotation.concurrent.GuardedBy; -import javax.annotation.concurrent.Immutable; -import javax.annotation.concurrent.ThreadSafe; -import org.openide.util.Exceptions; 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.CoordinationService; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; @@ -101,7 +98,6 @@ import org.sleuthkit.autopsy.ingest.IngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestJobStartResult; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestModuleError; -import org.sleuthkit.datamodel.Content; /** * An auto ingest manager is responsible for processing auto ingest jobs defined @@ -503,7 +499,6 @@ 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); } @@ -559,12 +554,10 @@ 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); } catch (CoordinationServiceException | InterruptedException ex) { - job.setPriority(oldPriority); throw new AutoIngestManagerException("Error updating case priority", ex); } } @@ -615,14 +608,12 @@ public final class AutoIngestManager extends Observable implements PropertyChang */ if (null != prioritizedJob) { ++maxPriority; - int oldPriority = prioritizedJob.getPriority(); - prioritizedJob.setPriority(maxPriority); try { this.updateCoordinationServiceNode(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()); @@ -1051,8 +1042,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(); @@ -1066,8 +1057,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()); @@ -1087,7 +1078,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang break; case DELETED: /* - * Ignore jobs marked as "deleted." + * Ignore jobs marked as "deleted." */ break; default: @@ -1247,48 +1238,38 @@ 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); 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); - } 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()); + /* + * Write the alert file and do the logging. + */ + AutoIngestAlertFile.create(caseDirectoryPath); } catch (AutoIngestAlertFileException ex) { SYS_LOGGER.log(Level.SEVERE, String.format("Error creating alert file for crashed job for %s", manifestPath), ex); } + } else { + job.setErrorsOccurred(false); } + if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) { job.setProcessingStatus(AutoIngestJob.ProcessingStatus.PENDING); if (null != caseDirectoryPath) { @@ -1302,13 +1283,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 { + updateCoordinationServiceNode(job); + } catch (CoordinationServiceException ex) { + SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifestPath), ex); + return; + } + + nodeData = new AutoIngestJobNodeData(job); + + if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) { + newPendingJobsList.add(job); + } else { + newCompletedJobsList.add(new AutoIngestJob(nodeData)); + } + } finally { try { manifestLock.release(); @@ -1459,7 +1459,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang */ private final class JobProcessingTask implements Runnable { - private static final String AUTO_INGEST_MODULE_OUTPUT_DIR = "AutoIngest"; private final Object ingestLock; private final Object pauseLock; @GuardedBy("pauseLock") @@ -2126,7 +2125,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 @@ -2222,7 +2222,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang return; } - DataSource dataSource = identifyDataSource(caseForJob); + DataSource dataSource = identifyDataSource(); if (null == dataSource) { currentJob.setProcessingStage(AutoIngestJob.Stage.COMPLETED, Date.from(Instant.now())); return; @@ -2275,7 +2275,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang * interrupted while blocked, i.e., * if auto ingest is shutting down. */ - private DataSource identifyDataSource(Case caseForJob) throws AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException { + private DataSource identifyDataSource() throws AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException { Manifest manifest = currentJob.getManifest(); Path manifestPath = manifest.getFilePath(); SYS_LOGGER.log(Level.INFO, "Identifying data source for {0} ", manifestPath); @@ -2294,7 +2294,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang String deviceId = manifest.getDeviceId(); return new DataSource(deviceId, dataSourcePath); } - + /** * Passes the data source for the current job through a data source * processor that adds it to the case database. @@ -2317,28 +2317,21 @@ public final class AutoIngestManager extends Observable implements PropertyChang 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); + 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); - // lookup all AutomatedIngestDataSourceProcessors - Collection processorCandidates = Lookup.getDefault().lookupAll(AutoIngestDataSourceProcessor.class); - - Map validDataSourceProcessorsMap = new HashMap<>(); - for (AutoIngestDataSourceProcessor processor : processorCandidates) { - try { - int confidence = processor.canProcess(dataSource.getPath()); - if (confidence > 0) { - validDataSourceProcessorsMap.put(processor, confidence); - } - } catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) { - SYS_LOGGER.log(Level.SEVERE, "Exception while determining whether data source processor {0} can process {1}", new Object[]{processor.getDataSourceType(), dataSource.getPath()}); - // rethrow the exception. It will get caught & handled upstream and will result in AIM auto-pause. - throw ex; - } + Map validDataSourceProcessorsMap; + try { + // lookup all AutomatedIngestDataSourceProcessors and poll which ones are able to process the current data source + validDataSourceProcessorsMap = DataSourceProcessorUtility.getDataSourceProcessor(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. + throw ex; } // did we find a data source processor that can process the data source @@ -2595,80 +2588,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang jobLogger.logFileExportError(); } } - - /** - * A "callback" 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 - class AddDataSourceCallback extends DataSourceProcessorCallback { - - private final Case caseForJob; - private final DataSource dataSourceInfo; - private final UUID taskId; - - /** - * Constructs a "callback" 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 caseForJob The case for the current job. - * @param dataSourceInfo The data source - * @param taskId The task id to associate with ingest job - * events. - */ - AddDataSourceCallback(Case caseForJob, DataSource dataSourceInfo, UUID taskId) { - this.caseForJob = caseForJob; - this.dataSourceInfo = dataSourceInfo; - this.taskId = taskId; - } - - /** - * 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 errorMessages, List dataSourceContent) { - if (!dataSourceContent.isEmpty()) { - caseForJob.notifyDataSourceAdded(dataSourceContent.get(0), taskId); - } else { - caseForJob.notifyFailedAddingDataSource(taskId); - } - dataSourceInfo.setDataSourceProcessorOutput(result, errorMessages, dataSourceContent); - dataSourceContent.addAll(dataSourceContent); - synchronized (ingestLock) { - ingestLock.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 errorMessages, List dataSources) { - done(result, errorMessages, dataSources); - } - - } - + /** * A data source processor progress monitor does nothing. There is * currently no mechanism for showing or recording data source processor @@ -3008,49 +2928,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang PARTIALLY_DELETED, FULLY_DELETED } - - @ThreadSafe - private static final class DataSource { - - private final String deviceId; - private final Path path; - private DataSourceProcessorResult resultCode; - private List errorMessages; - private List content; - - DataSource(String deviceId, Path path) { - this.deviceId = deviceId; - this.path = path; - } - - String getDeviceId() { - return deviceId; - } - - Path getPath() { - return this.path; - } - - synchronized void setDataSourceProcessorOutput(DataSourceProcessorResult result, List errorMessages, List content) { - this.resultCode = result; - this.errorMessages = new ArrayList<>(errorMessages); - this.content = new ArrayList<>(content); - } - - synchronized DataSourceProcessorResult getResultDataSourceProcessorResultCode() { - return resultCode; - } - - synchronized List getDataSourceProcessorErrorMessages() { - return new ArrayList<>(errorMessages); - } - - synchronized List getContent() { - return new ArrayList<>(content); - } - - } - + static final class AutoIngestManagerException extends Exception { private static final long serialVersionUID = 1L; From 29c25d71e6cbd59a64831a6ee0997091b81261cd Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 1 Nov 2017 16:35:44 -0400 Subject: [PATCH 27/69] Minor revision --- .../autopsy/experimental/autoingest/AutoIngestManager.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index a779085813..cf41d00df2 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -62,7 +62,6 @@ 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.CoordinationService; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; @@ -2125,8 +2124,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang Case.openAsCurrentCase(metadataFilePath.toString()); } else { caseDirectoryPath = PathUtils.createCaseFolderPath(rootOutputDirectory, caseName); - CaseDetails caseDetails = new CaseDetails(caseName, "", "", "", "", ""); - Case.createAsCurrentCase(CaseType.MULTI_USER_CASE, caseDirectoryPath.toString(), caseDetails); + Case.createAsCurrentCase(caseDirectoryPath.toString(), caseName, "", "", CaseType.MULTI_USER_CASE); /* * Sleep a bit before releasing the lock to ensure * that the new case folder is visible on the From d0e5f9d50b7c7f5c961e0611b93d38fdcce2deee Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 1 Nov 2017 16:40:55 -0400 Subject: [PATCH 28/69] Minor revision --- .../autoingest/AutoIngestManager.java | 177 +++++++++++++++--- 1 file changed, 155 insertions(+), 22 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index cf41d00df2..3f28487394 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -37,6 +37,7 @@ import java.time.Duration; import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.EnumSet; @@ -58,6 +59,9 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.stream.Collectors; import javax.annotation.concurrent.GuardedBy; +import javax.annotation.concurrent.Immutable; +import javax.annotation.concurrent.ThreadSafe; +import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case.CaseType; @@ -97,6 +101,7 @@ import org.sleuthkit.autopsy.ingest.IngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestJobStartResult; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestModuleError; +import org.sleuthkit.datamodel.Content; /** * An auto ingest manager is responsible for processing auto ingest jobs defined @@ -498,6 +503,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 +559,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); } catch (CoordinationServiceException | InterruptedException ex) { + job.setPriority(oldPriority); throw new AutoIngestManagerException("Error updating case priority", ex); } } @@ -607,12 +615,14 @@ public final class AutoIngestManager extends Observable implements PropertyChang */ if (null != prioritizedJob) { ++maxPriority; + int oldPriority = prioritizedJob.getPriority(); + prioritizedJob.setPriority(maxPriority); try { this.updateCoordinationServiceNode(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()); @@ -1041,8 +1051,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 +1066,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 +1087,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang break; case DELETED: /* - * Ignore jobs marked as "deleted." + * Ignore jobs marked as "deleted." */ break; default: @@ -1458,6 +1468,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang */ private final class JobProcessingTask implements Runnable { + private static final String AUTO_INGEST_MODULE_OUTPUT_DIR = "AutoIngest"; private final Object ingestLock; private final Object pauseLock; @GuardedBy("pauseLock") @@ -2220,7 +2231,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang return; } - DataSource dataSource = identifyDataSource(); + DataSource dataSource = identifyDataSource(caseForJob); if (null == dataSource) { currentJob.setProcessingStage(AutoIngestJob.Stage.COMPLETED, Date.from(Instant.now())); return; @@ -2273,7 +2284,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 DataSource identifyDataSource(Case caseForJob) throws AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException { Manifest manifest = currentJob.getManifest(); Path manifestPath = manifest.getFilePath(); SYS_LOGGER.log(Level.INFO, "Identifying data source for {0} ", manifestPath); @@ -2292,7 +2303,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang String deviceId = manifest.getDeviceId(); return new DataSource(deviceId, dataSourcePath); } - + /** * Passes the data source for the current job through a data source * processor that adds it to the case database. @@ -2315,21 +2326,28 @@ public final class AutoIngestManager extends Observable implements PropertyChang 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); + DataSourceProcessorCallback callBack = new AddDataSourceCallback(caseForJob, dataSource, taskId); DataSourceProcessorProgressMonitor progressMonitor = new DoNothingDSPProgressMonitor(); Path caseDirectoryPath = currentJob.getCaseDirectoryPath(); AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, manifest.getDataSourceFileName(), caseDirectoryPath); try { caseForJob.notifyAddingDataSource(taskId); - Map validDataSourceProcessorsMap; - try { - // lookup all AutomatedIngestDataSourceProcessors and poll which ones are able to process the current data source - validDataSourceProcessorsMap = DataSourceProcessorUtility.getDataSourceProcessor(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. - throw ex; + // lookup all AutomatedIngestDataSourceProcessors + Collection processorCandidates = Lookup.getDefault().lookupAll(AutoIngestDataSourceProcessor.class); + + Map validDataSourceProcessorsMap = new HashMap<>(); + for (AutoIngestDataSourceProcessor processor : processorCandidates) { + try { + int confidence = processor.canProcess(dataSource.getPath()); + if (confidence > 0) { + validDataSourceProcessorsMap.put(processor, confidence); + } + } catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) { + SYS_LOGGER.log(Level.SEVERE, "Exception while determining whether data source processor {0} can process {1}", new Object[]{processor.getDataSourceType(), dataSource.getPath()}); + // rethrow the exception. It will get caught & handled upstream and will result in AIM auto-pause. + throw ex; + } } // did we find a data source processor that can process the data source @@ -2586,7 +2604,80 @@ public final class AutoIngestManager extends Observable implements PropertyChang jobLogger.logFileExportError(); } } - + + /** + * A "callback" 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 + class AddDataSourceCallback extends DataSourceProcessorCallback { + + private final Case caseForJob; + private final DataSource dataSourceInfo; + private final UUID taskId; + + /** + * Constructs a "callback" 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 caseForJob The case for the current job. + * @param dataSourceInfo The data source + * @param taskId The task id to associate with ingest job + * events. + */ + AddDataSourceCallback(Case caseForJob, DataSource dataSourceInfo, UUID taskId) { + this.caseForJob = caseForJob; + this.dataSourceInfo = dataSourceInfo; + this.taskId = taskId; + } + + /** + * 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 errorMessages, List dataSourceContent) { + if (!dataSourceContent.isEmpty()) { + caseForJob.notifyDataSourceAdded(dataSourceContent.get(0), taskId); + } else { + caseForJob.notifyFailedAddingDataSource(taskId); + } + dataSourceInfo.setDataSourceProcessorOutput(result, errorMessages, dataSourceContent); + dataSourceContent.addAll(dataSourceContent); + synchronized (ingestLock) { + ingestLock.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 errorMessages, List dataSources) { + done(result, errorMessages, dataSources); + } + + } + /** * A data source processor progress monitor does nothing. There is * currently no mechanism for showing or recording data source processor @@ -2926,7 +3017,49 @@ public final class AutoIngestManager extends Observable implements PropertyChang PARTIALLY_DELETED, FULLY_DELETED } - + + @ThreadSafe + private static final class DataSource { + + private final String deviceId; + private final Path path; + private DataSourceProcessorResult resultCode; + private List errorMessages; + private List content; + + DataSource(String deviceId, Path path) { + this.deviceId = deviceId; + this.path = path; + } + + String getDeviceId() { + return deviceId; + } + + Path getPath() { + return this.path; + } + + synchronized void setDataSourceProcessorOutput(DataSourceProcessorResult result, List errorMessages, List content) { + this.resultCode = result; + this.errorMessages = new ArrayList<>(errorMessages); + this.content = new ArrayList<>(content); + } + + synchronized DataSourceProcessorResult getResultDataSourceProcessorResultCode() { + return resultCode; + } + + synchronized List getDataSourceProcessorErrorMessages() { + return new ArrayList<>(errorMessages); + } + + synchronized List getContent() { + return new ArrayList<>(content); + } + + } + static final class AutoIngestManagerException extends Exception { private static final long serialVersionUID = 1L; @@ -2941,4 +3074,4 @@ public final class AutoIngestManager extends Observable implements PropertyChang } -} +} \ No newline at end of file From 377075401ba73928d3ae7986681a440a270463db Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Wed, 1 Nov 2017 16:46:04 -0400 Subject: [PATCH 29/69] 3180: correct the typo --- ...{IntestFileFiltersTest.java => IngestFileFiltersTest.java} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename Core/test/unit/src/org/sleuthkit/autopsy/ingest/{IntestFileFiltersTest.java => IngestFileFiltersTest.java} (94%) diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/ingest/IntestFileFiltersTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java similarity index 94% rename from Core/test/unit/src/org/sleuthkit/autopsy/ingest/IntestFileFiltersTest.java rename to Core/test/unit/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java index b952462de8..29618e30ec 100755 --- a/Core/test/unit/src/org/sleuthkit/autopsy/ingest/IntestFileFiltersTest.java +++ b/Core/test/unit/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java @@ -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 From 536056f415b018924a35114b03f1adc1989ccd2a Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 1 Nov 2017 16:49:49 -0400 Subject: [PATCH 30/69] Removed unused import and variable. --- .../autopsy/experimental/autoingest/AutoIngestManager.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index 3f28487394..c169223396 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -61,7 +61,6 @@ import java.util.stream.Collectors; import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.ThreadSafe; -import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case.CaseType; @@ -122,7 +121,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang 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"; From 2ba9b1fa266f4ce64b919d4c928c28968bf13f98 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 3 Nov 2017 13:15:16 -0400 Subject: [PATCH 31/69] New generic status icon cell renderer. --- .../autopsy/casemodule/MultiUserCase.java | 285 ------------------ .../coreutils/CaseStatusIconCellRenderer.java | 58 ---- .../CenteredGrayableCellRenderer.java | 0 .../LongDateCellRenderer.java | 0 .../guiutils}/ShortDateCellRenderer.java | 0 .../autoingest/DurationCellRenderer.java | 98 ------ 6 files changed, 441 deletions(-) delete mode 100755 Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java delete mode 100755 Core/src/org/sleuthkit/autopsy/coreutils/CaseStatusIconCellRenderer.java rename {Experimental/src/org/sleuthkit/autopsy/experimental/autoingest => Core/src/org/sleuthkit/autopsy/guiutils}/CenteredGrayableCellRenderer.java (100%) rename Core/src/org/sleuthkit/autopsy/{coreutils => guiutils}/LongDateCellRenderer.java (100%) rename {Experimental/src/org/sleuthkit/autopsy/experimental/autoingest => Core/src/org/sleuthkit/autopsy/guiutils}/ShortDateCellRenderer.java (100%) delete mode 100755 Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/DurationCellRenderer.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java deleted file mode 100755 index e0bba29c43..0000000000 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2015-2017 Basis Technology Corp. - * Contact: carrier sleuthkit 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.Comparator; -import java.util.Date; -import java.util.Objects; -import java.util.logging.Level; -import org.sleuthkit.autopsy.coreutils.Logger; - -/** - * A representation of a multi-user case. - */ -class MultiUserCase implements Comparable { - - private static final Logger logger = Logger.getLogger(MultiUserCase.class.getName()); - private final Path caseDirectoryPath; - private final String caseDisplayName; - private final String metadataFileName; - private final Date createDate; - private final Date lastAccessedDate; - - /** - * Constructs a representation of a multi-user case - * - * @param caseDirectoryPath The case directory path. - * - * @throws CaseMetadata.CaseMetadataException If the CaseMetadata object - * cannot be constructed for the - * case display name. - * @throws MultiUserCaseException If no case metadata (.aut) - * file is found in the case - * directory. - */ - MultiUserCase(Path caseDirectoryPath) throws CaseMetadata.CaseMetadataException, MultiUserCaseException { - CaseMetadata caseMetadata = null; - - try { - caseMetadata = getCaseMetadataFromCaseDirectoryPath(caseDirectoryPath); - } catch (CaseMetadata.CaseMetadataException ex) { - logger.log(Level.SEVERE, String.format("Error reading the case metadata for %s.", caseDirectoryPath), ex); - throw ex; - } - - this.caseDirectoryPath = caseDirectoryPath; - caseDisplayName = caseMetadata.getCaseDisplayName(); - metadataFileName = caseMetadata.getFilePath().getFileName().toString(); - 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 based on the auto ingest result file in the - * case directory. - * - * @return See CaseStatus enum definition. - */ - CaseStatus getStatus() { - if(caseDirectoryPath.resolve("autoingest.alert").toFile().exists()) { - return CaseStatus.ALERT; - } else { - return CaseStatus.OK; - } - } - - /** - * 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 static 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 { - - /** - * 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 static 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); - } - } - - enum CaseStatus { - - OK, - ALERT - } - -} diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/CaseStatusIconCellRenderer.java b/Core/src/org/sleuthkit/autopsy/coreutils/CaseStatusIconCellRenderer.java deleted file mode 100755 index 4d782a6f57..0000000000 --- a/Core/src/org/sleuthkit/autopsy/coreutils/CaseStatusIconCellRenderer.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2015-2017 Basis Technology Corp. - * Contact: carrier sleuthkit 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.coreutils; - -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 an auto ingest alert file exists flag - * as a center-aligned icon, and grays out the cell if the table is disabled. - */ -public class CaseStatusIconCellRenderer extends GrayableCellRenderer { - - 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)); - - @Messages({ - "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" - }) - @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")); - } else { - setIcon(checkedIcon); - setToolTipText(org.openide.util.NbBundle.getMessage(CaseStatusIconCellRenderer.class, "CaseStatusIconCellRenderer.tooltiptext.ok")); - } - } - grayCellIfTableNotEnabled(table, isSelected); - - return this; - } -} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CenteredGrayableCellRenderer.java b/Core/src/org/sleuthkit/autopsy/guiutils/CenteredGrayableCellRenderer.java similarity index 100% rename from Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CenteredGrayableCellRenderer.java rename to Core/src/org/sleuthkit/autopsy/guiutils/CenteredGrayableCellRenderer.java diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/LongDateCellRenderer.java b/Core/src/org/sleuthkit/autopsy/guiutils/LongDateCellRenderer.java similarity index 100% rename from Core/src/org/sleuthkit/autopsy/coreutils/LongDateCellRenderer.java rename to Core/src/org/sleuthkit/autopsy/guiutils/LongDateCellRenderer.java diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ShortDateCellRenderer.java b/Core/src/org/sleuthkit/autopsy/guiutils/ShortDateCellRenderer.java similarity index 100% rename from Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ShortDateCellRenderer.java rename to Core/src/org/sleuthkit/autopsy/guiutils/ShortDateCellRenderer.java diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/DurationCellRenderer.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/DurationCellRenderer.java deleted file mode 100755 index c61e363222..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/DurationCellRenderer.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2015 Basis Technology Corp. - * Contact: carrier sleuthkit 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.Color; -import java.awt.Component; -import java.time.Duration; -import javax.swing.JTable; -import static javax.swing.SwingConstants.CENTER; -import org.sleuthkit.autopsy.coreutils.GrayableCellRenderer; - -/** - * A JTable cell renderer that renders a duration represented as a long as a - * 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 { - - private static final long serialVersionUID = 1L; - - DurationCellRenderer() { - setHorizontalAlignment(CENTER); - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - if (value instanceof Long) { - { - Duration d = Duration.ofMillis((long) value); - if (d.isNegative()) { - d = Duration.ofMillis(-(long) value); - } - - String result; - long days = d.toDays(); - long hours = d.minusDays(days).toHours(); - long minutes = d.minusDays(days).minusHours(hours).toMinutes(); - long seconds = d.minusDays(days).minusHours(hours).minusMinutes(minutes).getSeconds(); - - if (minutes > 0) { - if (hours > 0) { - if (days > 0) { - result = days + " d " + hours + " h " + minutes + " m " + seconds + " s"; - } else { - result = hours + " h " + minutes + " m " + seconds + " s"; - } - } else { - result = minutes + " m " + seconds + " s"; - } - } else { - result = seconds + " s"; - } - - setText(result); - } - } - grayCellIfTableNotEnabled(table, isSelected); - return this; - } - - void grayCellIfTableNotEnabled(JTable table, boolean isSelected) { - if (table.isEnabled()) { - /* - * The table is enabled, make the foreground and background the - * normal selected or unselected color. - */ - if (isSelected) { - setBackground(table.getSelectionBackground()); - setForeground(table.getSelectionForeground()); - } else { - setBackground(table.getBackground()); - setForeground(table.getForeground()); - } - } else { - /* - * The table is disabled, make the foreground and background gray. - */ - setBackground(Color.lightGray); - setForeground(Color.darkGray); - } - } -} From b5526ecf838da0aff20c142b54b1a371287863a7 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 3 Nov 2017 14:54:20 -0400 Subject: [PATCH 32/69] Revisions to multi-user cases panel code. --- Core/nbproject/project.xml | 1 + .../autopsy/casemodule/Bundle.properties | 2 +- .../autopsy/casemodule/CaseDeleteAction.java | 9 +- .../casemodule/CaseOpenMultiUserAction.java | 17 +- .../autopsy/casemodule/CueBannerPanel.java | 12 +- .../casemodule/MultiUserCaseManager.java | 258 +++++++++++++++++- .../casemodule/MultiUserCasesDialog.java | 20 +- .../casemodule/MultiUserCasesPanel.java | 101 ++++--- .../autopsy/coreutils/TimeStampUtils.java | 22 +- .../CenteredGrayableCellRenderer.java | 3 +- .../guiutils/DurationCellRenderer.java | 97 +++++++ .../GrayableCellRenderer.java | 2 +- .../guiutils/LongDateCellRenderer.java | 2 +- .../guiutils/ShortDateCellRenderer.java | 3 +- .../guiutils/StatusIconCellRenderer.java | 74 +++++ .../src/org/sleuthkit/autopsy/images/tick.png | Bin 0 -> 582 bytes .../sleuthkit/autopsy/images/warning16.png | Bin 0 -> 552 bytes .../autoingest/AutoIngestControlPanel.java | 13 +- .../autoingest/AutoIngestDashboard.java | 9 +- .../autoingest/AutoIngestManager.java | 5 +- .../experimental/autoingest/Bundle.properties | 3 - .../autopsy/experimental/autoingest/layer.xml | 25 +- .../AutoIngestSettingsPanel.form | 4 - .../AutoIngestSettingsPanel.java | 2 - 24 files changed, 529 insertions(+), 155 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/guiutils/DurationCellRenderer.java rename Core/src/org/sleuthkit/autopsy/{coreutils => guiutils}/GrayableCellRenderer.java (98%) create mode 100755 Core/src/org/sleuthkit/autopsy/guiutils/StatusIconCellRenderer.java create mode 100755 Core/src/org/sleuthkit/autopsy/images/tick.png create mode 100755 Core/src/org/sleuthkit/autopsy/images/warning16.png diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml index 25e17dd3eb..993af4bf6e 100755 --- a/Core/nbproject/project.xml +++ b/Core/nbproject/project.xml @@ -269,6 +269,7 @@ org.sleuthkit.autopsy.events org.sleuthkit.autopsy.externalresults org.sleuthkit.autopsy.filesearch + org.sleuthkit.autopsy.guiutils org.sleuthkit.autopsy.ingest org.sleuthkit.autopsy.keywordsearchservice org.sleuthkit.autopsy.menuactions diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index 5b80fd80ba..60db8edaf8 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -4,7 +4,7 @@ CTL_CaseCloseAct=Close Case 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 diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseDeleteAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseDeleteAction.java index b95ad78edf..66e983b1ce 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseDeleteAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseDeleteAction.java @@ -44,12 +44,15 @@ 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) -> { + /* + * A value of 'null' signifies that there is no case open. + */ setEnabled(null != evt.getNewValue()); }); } @@ -92,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()), @@ -107,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); } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java index 76607210c5..7a12b69cf7 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java @@ -18,13 +18,9 @@ */ package org.sleuthkit.autopsy.casemodule; -import java.awt.Dialog; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; -import javax.swing.JComponent; import javax.swing.JDialog; -import javax.swing.KeyStroke; import org.openide.awt.ActionID; import org.openide.awt.ActionReference; import org.openide.awt.ActionRegistration; @@ -33,7 +29,6 @@ import org.openide.util.NbBundle; import org.openide.util.actions.CallableSystemAction; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.core.UserPreferences; -import org.sleuthkit.autopsy.coreutils.NetworkUtils; /** * The action associated with the Open Multi-User Case menu item via the @@ -51,16 +46,8 @@ public final class CaseOpenMultiUserAction extends CallableSystemAction implemen private static JDialog multiUserCaseWindow; private static final String DISPLAY_NAME = Bundle.CTL_CaseOpenMultiUserAction(); - private static final String LOCAL_HOST_NAME = NetworkUtils.getLocalHostName(); - private static final String REVIEW_MODE_TITLE = "Open Multi-User Case (" + LOCAL_HOST_NAME + ")"; public CaseOpenMultiUserAction() {} - - public static void closeMultiUserCasesWindow() { - if (null != multiUserCaseWindow) { - multiUserCaseWindow.setVisible(false); - } - } @Override public boolean isEnabled() { @@ -68,10 +55,10 @@ public final class CaseOpenMultiUserAction extends CallableSystemAction implemen } /** - * Pops up a case selection panel to allow the user to selecte a multi-user + * Pops up a case selection panel to allow the user to select a multi-user * case to open. * - * @param e The action event. + * @param event The action event. */ @Override public void actionPerformed(ActionEvent event) { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java index 24c714eb5b..2c81d100e4 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java @@ -38,13 +38,11 @@ import org.sleuthkit.autopsy.core.UserPreferences; public class CueBannerPanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; - private static final String REVIEW_MODE_TITLE = "Open Multi-User Case"; /* * This is field is static for the sake of the closeOpenRecentCasesWindow * method. */ private static JDialog recentCasesWindow; - private static JDialog multiUserCaseWindow; public static void closeOpenRecentCasesWindow() { if (null != recentCasesWindow) { @@ -52,12 +50,6 @@ public class CueBannerPanel extends javax.swing.JPanel { } } - public static void closeMultiUserCasesWindow() { - if (null != multiUserCaseWindow) { - multiUserCaseWindow.setVisible(false); - } - } - public CueBannerPanel() { initComponents(); initRecentCasesWindow(); @@ -284,9 +276,7 @@ public class CueBannerPanel extends javax.swing.JPanel { }//GEN-LAST:event_openRecentCaseButtonActionPerformed private void openMultiUserCaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openMultiUserCaseButtonActionPerformed - if(multiUserCaseWindow == null) { - multiUserCaseWindow = MultiUserCasesDialog.getInstance(); - } + MultiUserCasesDialog multiUserCaseWindow = MultiUserCasesDialog.getInstance(); multiUserCaseWindow.setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); multiUserCaseWindow.setVisible(true); }//GEN-LAST:event_openMultiUserCaseButtonActionPerformed diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java index 3101461443..d0baf94bc9 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java @@ -19,20 +19,29 @@ 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.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 LOG_FILE_NAME = "auto_ingest_log.txt"; private static MultiUserCaseManager instance; - private CoordinationService coordinationService; /** @@ -79,9 +88,10 @@ final class MultiUserCaseManager { File[] autFiles = caseFolder.listFiles((dir, name) -> name.toLowerCase().endsWith(".aut")); if(autFiles != null && autFiles.length > 0) { try { - cases.add(new MultiUserCase(casePath)); + CaseMetadata caseMetadata = new CaseMetadata(Paths.get(autFiles[0].getAbsolutePath())); + cases.add(new MultiUserCase(casePath, caseMetadata)); } catch (CaseMetadata.CaseMetadataException | MultiUserCase.MultiUserCaseException ex) { - // Ignore and continue. + LOGGER.log(Level.SEVERE, String.format("Error reading case metadata file '%s'.", autFiles[0].getAbsolutePath()), ex); } } } @@ -133,4 +143,246 @@ final class MultiUserCaseManager { } } + + /** + * A representation of a multi-user case. + */ + static class MultiUserCase implements Comparable { + + private final Path caseDirectoryPath; + private final String caseDisplayName; + private final String metadataFileName; + private final Date createDate; + private final Date lastAccessedDate; + + /** + * 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) throws MultiUserCaseException { + this.caseDirectoryPath = caseDirectoryPath; + caseDisplayName = caseMetadata.getCaseDisplayName(); + metadataFileName = caseMetadata.getFilePath().getFileName().toString(); + 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 based on the auto ingest result file in the + * case directory. + * + * @return See CaseStatus enum definition. + */ + CaseStatus getStatus() { + if(caseDirectoryPath.resolve("autoingest.alert").toFile().exists()) { + return CaseStatus.ALERT; + } else { + return CaseStatus.OK; + } + } + + /** + * 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 { + + /** + * 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 + } + } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesDialog.java index b6d9feeb7e..8c90aeccb4 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesDialog.java @@ -28,9 +28,11 @@ import org.openide.windows.WindowManager; /** * This class extends a JDialog and maintains the MultiUserCasesPanel. */ -public class MultiUserCasesDialog extends JDialog { +final class MultiUserCasesDialog extends JDialog { + + private static final long serialVersionUID = 1L; private static final String REVIEW_MODE_TITLE = "Open Multi-User Case"; - private final MultiUserCasesPanel multiUserCasesPanel; + private static MultiUserCasesPanel multiUserCasesPanel; private static MultiUserCasesDialog instance; /** @@ -41,6 +43,7 @@ public class MultiUserCasesDialog extends JDialog { static public MultiUserCasesDialog getInstance() { if(instance == null) { instance = new MultiUserCasesDialog(); + instance.init(); } return instance; } @@ -48,18 +51,23 @@ public class MultiUserCasesDialog extends JDialog { /** * Constructs a MultiUserCasesDialog object. */ - MultiUserCasesDialog() { + 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(); + multiUserCasesPanel = new MultiUserCasesPanel(this); add(multiUserCasesPanel); pack(); setResizable(false); @@ -74,7 +82,7 @@ public class MultiUserCasesDialog extends JDialog { @Override public void setVisible(boolean value) { if(value) { - multiUserCasesPanel.refreshCasesTable(); + multiUserCasesPanel.refresh(); } super.setVisible(value); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java index 42201e5850..133d3e2671 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java @@ -20,35 +20,34 @@ package org.sleuthkit.autopsy.casemodule; import java.awt.Cursor; import java.awt.Desktop; -import java.awt.EventQueue; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Date; import java.util.List; -import java.util.concurrent.ExecutionException; import java.util.logging.Level; +import javax.swing.JDialog; import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; -import javax.swing.SwingWorker; import javax.swing.event.ListSelectionEvent; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableColumn; -import org.sleuthkit.autopsy.coreutils.CaseStatusIconCellRenderer; -import org.sleuthkit.autopsy.coreutils.GrayableCellRenderer; +import org.sleuthkit.autopsy.casemodule.MultiUserCaseManager.MultiUserCase; +import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.LongDateCellRenderer; +import org.sleuthkit.autopsy.guiutils.LongDateCellRenderer; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; +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. */ -public class MultiUserCasesPanel extends javax.swing.JPanel { +final class MultiUserCasesPanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; private static final Logger LOGGER = Logger.getLogger(MultiUserCasesPanel.class.getName()); private static final String LOG_FILE_NAME = "auto_ingest_log.txt"; - private static final MultiUserCase.LastAccessedDateDescendingComparator REVERSE_DATE_MODIFIED_COMPARATOR = new MultiUserCase.LastAccessedDateDescendingComparator(); + 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; @@ -85,12 +84,14 @@ public class MultiUserCasesPanel extends javax.swing.JPanel { 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; + private JDialog parentDialog; /** * Constructs a panel that allows a user to open cases created by automated * ingest. */ - MultiUserCasesPanel() { + MultiUserCasesPanel(JDialog parentDialog) { + this.parentDialog = parentDialog; caseTableModel = new DefaultTableModel(columnNames, 0) { private static final long serialVersionUID = 1L; @@ -137,7 +138,7 @@ public class MultiUserCasesPanel extends javax.swing.JPanel { 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); @@ -163,42 +164,33 @@ public class MultiUserCasesPanel extends javax.swing.JPanel { * Gets the list of cases known to the review mode cases manager and * refreshes the cases table. */ - void refreshCasesTable() { - EventQueue.invokeLater(() -> { - setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - }); - - synchronized(this) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - try { - currentlySelectedCase = getSelectedCase(); - MultiUserCaseManager manager = MultiUserCaseManager.getInstance(); - List 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(), - (MultiUserCase.CaseStatus.OK != autoIngestCase.getStatus()), - autoIngestCase.getCaseDirectoryPath().toString(), - autoIngestCase.getMetadataFileName()}); - } - } - setSelectedCase(currentlySelectedCase); - setButtons(); - } catch (Exception ex) { - LOGGER.log(Level.SEVERE, "Unexpected exception while refreshing the table.", ex); //NON-NLS - } finally { - setCursor(null); - } + void refresh() { + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + + try { + currentlySelectedCase = getSelectedCase(); + MultiUserCaseManager manager = MultiUserCaseManager.getInstance(); + List 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); } } @@ -282,8 +274,9 @@ public class MultiUserCasesPanel extends javax.swing.JPanel { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); try { StartupWindowProvider.getInstance().close(); - CueBannerPanel.closeMultiUserCasesWindow(); - CaseOpenMultiUserAction.closeMultiUserCasesWindow(); + if (parentDialog != null) { + parentDialog.setVisible(false); + } MultiUserCaseManager.getInstance().openCase(caseMetadataFilePath); } catch (CaseActionException | MultiUserCaseManager.MultiUserCaseManagerException ex) { if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) { @@ -491,7 +484,7 @@ public class MultiUserCasesPanel extends javax.swing.JPanel { int modelRow = casesTable.convertRowIndexToModel(casesTable.getSelectedRow()); 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(); @@ -503,30 +496,30 @@ public class MultiUserCasesPanel extends javax.swing.JPanel { * @param evt -- The event that caused this to be called */ private void bnRefreshActionPerformed(java.awt.event.ActionEvent evt) { - refreshCasesTable(); + refresh(); } private void rbDaysItemStateChanged(java.awt.event.ItemEvent evt) { if (rbDays.isSelected()) { - refreshCasesTable(); + refresh(); } } private void rbAllCasesItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbAllCasesItemStateChanged if (rbAllCases.isSelected()) { - refreshCasesTable(); + refresh(); } }//GEN-LAST:event_rbAllCasesItemStateChanged private void rbMonthsItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbMonthsItemStateChanged if (rbMonths.isSelected()) { - refreshCasesTable(); + refresh(); } }//GEN-LAST:event_rbMonthsItemStateChanged private void rbWeeksItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbWeeksItemStateChanged if (rbWeeks.isSelected()) { - refreshCasesTable(); + refresh(); } }//GEN-LAST:event_rbWeeksItemStateChanged diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/TimeStampUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/TimeStampUtils.java index 4b22a6010d..e14b5c5897 100755 --- a/Core/src/org/sleuthkit/autopsy/coreutils/TimeStampUtils.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/TimeStampUtils.java @@ -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 * diff --git a/Core/src/org/sleuthkit/autopsy/guiutils/CenteredGrayableCellRenderer.java b/Core/src/org/sleuthkit/autopsy/guiutils/CenteredGrayableCellRenderer.java index 04422cd63a..af37f3f2e3 100755 --- a/Core/src/org/sleuthkit/autopsy/guiutils/CenteredGrayableCellRenderer.java +++ b/Core/src/org/sleuthkit/autopsy/guiutils/CenteredGrayableCellRenderer.java @@ -16,10 +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 static javax.swing.SwingConstants.CENTER; -import org.sleuthkit.autopsy.coreutils.GrayableCellRenderer; /** * A JTable cell renderer that center-aligns cell content and grays out the cell diff --git a/Core/src/org/sleuthkit/autopsy/guiutils/DurationCellRenderer.java b/Core/src/org/sleuthkit/autopsy/guiutils/DurationCellRenderer.java new file mode 100755 index 0000000000..970dafacfc --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/guiutils/DurationCellRenderer.java @@ -0,0 +1,97 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2015-2017 Basis Technology Corp. + * Contact: carrier sleuthkit 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.Color; +import java.awt.Component; +import java.time.Duration; +import javax.swing.JTable; +import static javax.swing.SwingConstants.CENTER; + +/** + * A JTable cell renderer that renders a duration represented as a long as a + * string with days, hours, minutes, and seconds components. It center-aligns + * cell content and grays out the cell if the table is disabled. + */ +public class DurationCellRenderer extends GrayableCellRenderer { + + private static final long serialVersionUID = 1L; + + public DurationCellRenderer() { + setHorizontalAlignment(CENTER); + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + if (value instanceof Long) { + { + Duration d = Duration.ofMillis((long) value); + if (d.isNegative()) { + d = Duration.ofMillis(-(long) value); + } + + String result; + long days = d.toDays(); + long hours = d.minusDays(days).toHours(); + long minutes = d.minusDays(days).minusHours(hours).toMinutes(); + long seconds = d.minusDays(days).minusHours(hours).minusMinutes(minutes).getSeconds(); + + if (minutes > 0) { + if (hours > 0) { + if (days > 0) { + result = days + " d " + hours + " h " + minutes + " m " + seconds + " s"; + } else { + result = hours + " h " + minutes + " m " + seconds + " s"; + } + } else { + result = minutes + " m " + seconds + " s"; + } + } else { + result = seconds + " s"; + } + + setText(result); + } + } + grayCellIfTableNotEnabled(table, isSelected); + return this; + } + + void grayCellIfTableNotEnabled(JTable table, boolean isSelected) { + if (table.isEnabled()) { + /* + * The table is enabled, make the foreground and background the + * normal selected or unselected color. + */ + if (isSelected) { + setBackground(table.getSelectionBackground()); + setForeground(table.getSelectionForeground()); + } else { + setBackground(table.getBackground()); + setForeground(table.getForeground()); + } + } else { + /* + * The table is disabled, make the foreground and background gray. + */ + setBackground(Color.lightGray); + setForeground(Color.darkGray); + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/GrayableCellRenderer.java b/Core/src/org/sleuthkit/autopsy/guiutils/GrayableCellRenderer.java similarity index 98% rename from Core/src/org/sleuthkit/autopsy/coreutils/GrayableCellRenderer.java rename to Core/src/org/sleuthkit/autopsy/guiutils/GrayableCellRenderer.java index 479f30bee2..53031faae3 100755 --- a/Core/src/org/sleuthkit/autopsy/coreutils/GrayableCellRenderer.java +++ b/Core/src/org/sleuthkit/autopsy/guiutils/GrayableCellRenderer.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.coreutils; +package org.sleuthkit.autopsy.guiutils; import java.awt.Color; import java.awt.Component; diff --git a/Core/src/org/sleuthkit/autopsy/guiutils/LongDateCellRenderer.java b/Core/src/org/sleuthkit/autopsy/guiutils/LongDateCellRenderer.java index e347b2d28a..373e4e2501 100755 --- a/Core/src/org/sleuthkit/autopsy/guiutils/LongDateCellRenderer.java +++ b/Core/src/org/sleuthkit/autopsy/guiutils/LongDateCellRenderer.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.coreutils; +package org.sleuthkit.autopsy.guiutils; import java.awt.Component; import java.text.SimpleDateFormat; diff --git a/Core/src/org/sleuthkit/autopsy/guiutils/ShortDateCellRenderer.java b/Core/src/org/sleuthkit/autopsy/guiutils/ShortDateCellRenderer.java index f2670fa1b7..299880f1c0 100755 --- a/Core/src/org/sleuthkit/autopsy/guiutils/ShortDateCellRenderer.java +++ b/Core/src/org/sleuthkit/autopsy/guiutils/ShortDateCellRenderer.java @@ -16,14 +16,13 @@ * 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; import static javax.swing.SwingConstants.CENTER; -import org.sleuthkit.autopsy.coreutils.GrayableCellRenderer; /** * A JTable cell renderer that renders a date represented as a long as a diff --git a/Core/src/org/sleuthkit/autopsy/guiutils/StatusIconCellRenderer.java b/Core/src/org/sleuthkit/autopsy/guiutils/StatusIconCellRenderer.java new file mode 100755 index 0000000000..b7ee58e4d4 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/guiutils/StatusIconCellRenderer.java @@ -0,0 +1,74 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2015-2017 Basis Technology Corp. + * Contact: carrier sleuthkit 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 + } +} diff --git a/Core/src/org/sleuthkit/autopsy/images/tick.png b/Core/src/org/sleuthkit/autopsy/images/tick.png new file mode 100755 index 0000000000000000000000000000000000000000..a7d7a96be3f2282a62e3c0733bac89c7f6de7b4a GIT binary patch literal 582 zcmV-M0=fN(P)tYd4K$mX5uyr2F@fdffp{&DSHtl4|Bn9=ukpCx`#%PTUr-D(@b7;C zhJXJjrnw{;1KBM=6&|E`fsNrGL!Y6%zUh}QUl`(@V)PmQFtotEKmafTHP0uP}7&%m4pcKQ#X)BiAJ2y+PrtBI>9eEIt2-_c7)?*Lsf z5vX5*Af@m-wBJRV%#Fiz=BdPr0!2^az8K(fJ0K@xl?-_o)`1bna-SH57SeZUButL)d$cI_) zkpl5Q!w#U+YtHUCagF&eebP3jhEB literal 0 HcmV?d00001 diff --git a/Core/src/org/sleuthkit/autopsy/images/warning16.png b/Core/src/org/sleuthkit/autopsy/images/warning16.png new file mode 100755 index 0000000000000000000000000000000000000000..f5ba881738ae3072e476f3ddbd7dd34d642f06d6 GIT binary patch literal 552 zcmV+@0@wYCP)A&a_P7S}o zG!s6}jEu~GKp4p&41mvo3NbA|1~KhGFq>2ZZB(et$g5@cY9-1{tFW22MeRe4v~wF$QERIaM<- z{{O*nd`23>@mYBc|Np&XP;x8-%MmglnP1j4N=(g;;pf|paKWFi*D(ky8Zq$8n1Dhw z4W9v-%1)IGf4<*f`2Xh#iNdNA(_lT4EX==BZIP28N-#eIhh~>reEIz qPU=w%q=BsSelect 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 diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/layer.xml b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/layer.xml index 56ad444eb0..ced44d8569 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/layer.xml +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/layer.xml @@ -2,20 +2,6 @@ - - - - - - - - - - - - @@ -23,19 +9,12 @@ - - - - - - - - + - + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.form b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.form index 9965d1ad8f..68002e8055 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.form +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.form @@ -1,10 +1,6 @@
- - - - diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.java index 892a27aab6..0d449fdb02 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.java @@ -583,7 +583,6 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel { // //GEN-BEGIN:initComponents private void initComponents() { - modeRadioButtons = new javax.swing.ButtonGroup(); nodeScrollPane = new javax.swing.JScrollPane(); nodePanel = new javax.swing.JPanel(); cbJoinAutoIngestCluster = new javax.swing.JCheckBox(); @@ -1211,7 +1210,6 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel { private javax.swing.JLabel jLabelSelectOutputFolder; private javax.swing.JLabel jLabelTaskDescription; 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; From a9b8f04f359ea9e75ac8b13b697953a5180432cb Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 3 Nov 2017 14:57:33 -0400 Subject: [PATCH 33/69] CaseDetails method change --- .../autopsy/experimental/autoingest/AutoIngestManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index b2ca78cda1..b621cb514f 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -2115,7 +2115,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang Case.openAsCurrentCase(metadataFilePath.toString()); } else { caseDirectoryPath = PathUtils.createCaseFolderPath(rootOutputDirectory, caseName); - CaseDetails caseDetails = new CaseDetails(caseName, "", "", "", "", ""); //DLG: Update this. + CaseDetails caseDetails = new CaseDetails(caseName); Case.createAsCurrentCase(CaseType.MULTI_USER_CASE, caseDirectoryPath.toString(), caseDetails); /* * Sleep a bit before releasing the lock to ensure From 0dfdcf9f1c9a60fee59868640e7e9a18280b3475 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 3 Nov 2017 15:10:14 -0400 Subject: [PATCH 34/69] Auto ingest metrics feature --- .../autopsy/casemodule/CaseDeleteAction.java | 3 +- .../autopsy/casemodule/CaseMetadata.java | 11 + .../casemodule/CaseOpenMultiUserAction.java | 36 +- .../autopsy/casemodule/CueBannerPanel.java | 23 +- .../autopsy/casemodule/MultiUserCase.java | 114 +++- .../casemodule/MultiUserCaseManager.java | 4 + .../casemodule/MultiUserCasePanel.form | 230 ------- .../casemodule/MultiUserCasePanel.java | 562 ------------------ .../datamodel/AbstractSqlEamDb.java | 0 .../centralrepository/datamodel/EamDb.java | 0 .../datamodel/SqliteEamDb.java | 0 .../eventlisteners/CaseEventListener.java | 0 .../eventlisteners/IngestEventsListener.java | 0 .../ingestmodule/IngestModule.java | 0 .../autopsy/core/UserPreferences.java | 4 +- .../sleuthkit/autopsy/core/timelineWsmode.xml | 0 .../autopsy/corecomponents/Installer.java | 19 + .../FileSystemDetailsAction.java | 0 .../autoingest/AutoIngestCaseOpenAction.java | 1 - .../autoingest/AutoIngestDashboard.form | 33 +- .../autoingest/AutoIngestDashboard.java | 46 +- .../AutoIngestDashboardOpenAction.java | 1 - .../autoingest/AutoIngestMonitor.java | 107 +++- .../experimental/autoingest/Bundle.properties | 5 + .../autoingest/CaseImportPanel.java | 1 - .../autoingest/dashboardWsmode.xml | 0 .../imagegallery/ImageGalleryWsmode.xml | 0 .../sleuthkit/autopsy/imagegallery/layer.xml | 0 .../keywordsearch/CreditCardValidator.java | 0 .../CreditCardValidatorTest.java | 0 docs/doxygen-user/central_repo.dox | 0 .../images/central_repo_content_viewer.png | Bin .../images/central_repo_interesting_items.png | Bin .../images/central_repo_manage_tags.png | Bin .../images/central_repo_options.png | Bin .../images/central_repo_postgres.png | Bin .../images/central_repo_sqlite.png | Bin .../images/central_repo_tag_file.png | Bin .../images/central_repo_types.png | Bin .../images/email_datasource_tree.png | Bin .../images/messages_datasource_tree.png | Bin ruleset.xml | 0 42 files changed, 312 insertions(+), 888 deletions(-) delete mode 100755 Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.form delete mode 100755 Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.java mode change 100644 => 100755 Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java mode change 100644 => 100755 Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java mode change 100644 => 100755 Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java mode change 100644 => 100755 Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java mode change 100644 => 100755 Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java mode change 100644 => 100755 Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java mode change 100644 => 100755 Core/src/org/sleuthkit/autopsy/core/timelineWsmode.xml mode change 100644 => 100755 Core/src/org/sleuthkit/autopsy/directorytree/FileSystemDetailsAction.java mode change 100644 => 100755 Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/dashboardWsmode.xml mode change 100644 => 100755 ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryWsmode.xml mode change 100644 => 100755 ImageGallery/src/org/sleuthkit/autopsy/imagegallery/layer.xml mode change 100644 => 100755 KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/CreditCardValidator.java mode change 100644 => 100755 KeywordSearch/test/unit/src/org/sleuthkit/autopsy/keywordsearch/CreditCardValidatorTest.java mode change 100644 => 100755 docs/doxygen-user/central_repo.dox mode change 100644 => 100755 docs/doxygen-user/images/central_repo_content_viewer.png mode change 100644 => 100755 docs/doxygen-user/images/central_repo_interesting_items.png mode change 100644 => 100755 docs/doxygen-user/images/central_repo_manage_tags.png mode change 100644 => 100755 docs/doxygen-user/images/central_repo_options.png mode change 100644 => 100755 docs/doxygen-user/images/central_repo_postgres.png mode change 100644 => 100755 docs/doxygen-user/images/central_repo_sqlite.png mode change 100644 => 100755 docs/doxygen-user/images/central_repo_tag_file.png mode change 100644 => 100755 docs/doxygen-user/images/central_repo_types.png mode change 100644 => 100755 docs/doxygen-user/images/email_datasource_tree.png mode change 100644 => 100755 docs/doxygen-user/images/messages_datasource_tree.png mode change 100644 => 100755 ruleset.xml diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseDeleteAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseDeleteAction.java index 3ef30f2594..dcda423c18 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseDeleteAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseDeleteAction.java @@ -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; /** @@ -51,7 +50,7 @@ final class CaseDeleteAction extends CallableSystemAction { 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); + setEnabled(null != evt.getNewValue() && ((Case)evt.getNewValue()).getCaseType() != Case.CaseType.MULTI_USER_CASE); }); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java index 1f4c5b7912..dee10f0ca1 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java @@ -172,6 +172,17 @@ public final class CaseMetadata { public String getCaseDirectory() { return metadataFilePath.getParent().toString(); } + + /** + * Gets the full case directory path. + * + * @return The case directory path. + */ + public String getCaseDirectoryPath() { + String fileName = metadataFilePath.getFileName().toString(); + String caseDirectoryPath = metadataFilePath.toString(); + return caseDirectoryPath.substring(0, caseDirectoryPath.lastIndexOf(fileName)); + } /** * Gets the case type. diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java index aa9b0eac6a..76607210c5 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java @@ -31,16 +31,13 @@ import org.openide.awt.ActionRegistration; import org.openide.util.HelpCtx; import org.openide.util.NbBundle; import org.openide.util.actions.CallableSystemAction; -import org.openide.util.lookup.ServiceProvider; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.core.UserPreferences; -import static org.sleuthkit.autopsy.core.UserPreferences.SelectedMode.REVIEW; import org.sleuthkit.autopsy.coreutils.NetworkUtils; /** - * The action associated with the Case/Open Case menu item via the layer.xml - * file, a toolbar button, and the Create New Case button of the start up window - * that allows a user to open a case. It opens an existing case. + * 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). */ @@ -57,27 +54,7 @@ public final class CaseOpenMultiUserAction extends CallableSystemAction implemen private static final String LOCAL_HOST_NAME = NetworkUtils.getLocalHostName(); private static final String REVIEW_MODE_TITLE = "Open Multi-User Case (" + LOCAL_HOST_NAME + ")"; - /** - * Constructs the action associated with the Case/Open Case menu item via - * the layer.xml file, a toolbar button, and the Create New Case button of - * the start up window that allows a user to open a case. It opens an - * existing case. - * - */ - public CaseOpenMultiUserAction() { - multiUserCaseWindow = new JDialog( - WindowManager.getDefault().getMainWindow(), - REVIEW_MODE_TITLE, - Dialog.ModalityType.APPLICATION_MODAL); - multiUserCaseWindow.getRootPane().registerKeyboardAction( - e -> { - multiUserCaseWindow.setVisible(false); - }, - KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW); - multiUserCaseWindow.add(new MultiUserCasePanel()); - multiUserCaseWindow.pack(); - multiUserCaseWindow.setResizable(false); - } + public CaseOpenMultiUserAction() {} public static void closeMultiUserCasesWindow() { if (null != multiUserCaseWindow) { @@ -91,13 +68,16 @@ public final class CaseOpenMultiUserAction extends CallableSystemAction implemen } /** - * Pops up a file chooser to allow the user to select a case metadata file - * (.aut file) and attempts to open the case described by the file. + * Pops up a case selection panel to allow the user to selecte a multi-user + * case to open. * * @param e The action event. */ @Override public void actionPerformed(ActionEvent event) { + if(multiUserCaseWindow == null) { + multiUserCaseWindow = MultiUserCasesDialog.getInstance(); + } multiUserCaseWindow.setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); multiUserCaseWindow.setVisible(true); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java index 48e54a3f9f..c4c15fdd91 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java @@ -31,7 +31,6 @@ import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.core.UserPreferences; -import org.sleuthkit.autopsy.coreutils.NetworkUtils; /* * The panel in the default Autopsy startup window. @@ -39,8 +38,7 @@ 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 = "Open Multi-User Case (" + LOCAL_HOST_NAME + ")"; + private static final String REVIEW_MODE_TITLE = "Open Multi-User Case"; /* * This is field is static for the sake of the closeOpenRecentCasesWindow * method. @@ -91,7 +89,6 @@ public class CueBannerPanel extends javax.swing.JPanel { private void customizeComponents() { initRecentCasesWindow(); - initMultiUserCasesWindow(); } private void initRecentCasesWindow() { @@ -116,21 +113,6 @@ public class CueBannerPanel extends javax.swing.JPanel { recentCasesWindow.pack(); recentCasesWindow.setResizable(false); } - - private void initMultiUserCasesWindow() { - multiUserCaseWindow = new JDialog( - WindowManager.getDefault().getMainWindow(), - REVIEW_MODE_TITLE, - Dialog.ModalityType.APPLICATION_MODAL); - multiUserCaseWindow.getRootPane().registerKeyboardAction( - e -> { - multiUserCaseWindow.setVisible(false); - }, - KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW); - multiUserCaseWindow.add(new MultiUserCasePanel()); - multiUserCaseWindow.pack(); - multiUserCaseWindow.setResizable(false); - } private void enableComponents() { boolean enableOpenRecentCaseButton = (RecentCases.getInstance().getTotalRecentCases() > 0); @@ -306,6 +288,9 @@ public class CueBannerPanel extends javax.swing.JPanel { }//GEN-LAST:event_openRecentCaseButtonActionPerformed private void openMultiUserCaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openMultiUserCaseButtonActionPerformed + if(multiUserCaseWindow == null) { + multiUserCaseWindow = MultiUserCasesDialog.getInstance(); + } multiUserCaseWindow.setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); multiUserCaseWindow.setVisible(true); }//GEN-LAST:event_openMultiUserCaseButtonActionPerformed diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java index d1a2bc65da..8ecc1c91e2 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java @@ -18,15 +18,16 @@ */ 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.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; import org.sleuthkit.autopsy.coreutils.TimeStampUtils; @@ -46,11 +47,27 @@ class MultiUserCase implements Comparable { * Constructs a representation of case created by automated ingest. * * @param caseDirectoryPath The case directory path. + * + * @throws CaseMetadata.CaseMetadataException If the CaseMetadata object + * cannot be constructed for the + * case display name. + * @throws MultiUserCaseException If no case metadata (.aut) + * file is found in the case + * directory. */ - MultiUserCase(Path caseDirectoryPath) { + MultiUserCase(Path caseDirectoryPath) throws CaseMetadata.CaseMetadataException, MultiUserCaseException { + CaseMetadata caseMetadata = null; + + try { + caseMetadata = getCaseMetadataFromCaseDirectoryPath(caseDirectoryPath); + } catch (CaseMetadata.CaseMetadataException ex) { + logger.log(Level.SEVERE, String.format("Error reading the case metadata for %s.", caseDirectoryPath), ex); + throw ex; + } + this.caseDirectoryPath = caseDirectoryPath; - caseName = getCaseNameFromCaseDirectoryPath(caseDirectoryPath); - metadataFilePath = caseDirectoryPath.resolve(caseName + CaseMetadata.getFileExtension()); + caseName = caseMetadata.getCaseDisplayName(); + metadataFilePath = caseMetadata.getFilePath(); BasicFileAttributes fileAttrs = null; try { fileAttrs = Files.readAttributes(metadataFilePath, BasicFileAttributes.class); @@ -103,6 +120,15 @@ class MultiUserCase implements Comparable { Date getLastAccessedDate() { return this.lastAccessedDate; } + + /** + * Gets the full path of the metadata (.aut) file. + * + * @return The metadata file path. + */ + Path getMetadataFilePath() { + return this.metadataFilePath; + } /** * Gets the status of this case based on the auto ingest result file in the @@ -119,19 +145,48 @@ class MultiUserCase implements Comparable { } /** - * Extracts the case name from a case folder path. + * Gets the case metadata from a case directory path. * - * @param caseFolderPath A case folder path. + * @param caseDirectoryPath The case directory path. * - * @return A case name, with the time stamp suffix removed. + * @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. */ - static String getCaseNameFromCaseDirectoryPath(Path caseFolderPath) { - String caseName = caseFolderPath.getFileName().toString(); - if (caseName.length() > TimeStampUtils.getTimeStampLength()) { - return caseName.substring(0, caseName.length() - TimeStampUtils.getTimeStampLength()); - } else { - return caseName; + private static CaseMetadata getCaseMetadataFromCaseDirectoryPath(Path caseDirectoryPath) throws CaseMetadata.CaseMetadataException, MultiUserCaseException { + CaseMetadata caseMetadata = null; + + File directory = new File(caseDirectoryPath.toString()); + if (directory.isDirectory()) { + String fileNamePrefix = directory.getName(); + if (TimeStampUtils.endsWithTimeStamp(fileNamePrefix)) { + fileNamePrefix = fileNamePrefix.substring(0, fileNamePrefix.length() - TimeStampUtils.getTimeStampLength()); + } + + 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; } /** @@ -169,7 +224,7 @@ class MultiUserCase implements Comparable { /** * Compares this AutopIngestCase object with abnother MultiUserCase object - for order. + * for order. */ @Override public int compareTo(MultiUserCase other) { @@ -183,7 +238,7 @@ class MultiUserCase implements Comparable { /** * Compares two MultiUserCase objects for order based on last accessed - date (descending). + * date (descending). * * @param object The first MultiUserCase object * @param otherObject The second AuotIngestCase object. @@ -196,6 +251,35 @@ class MultiUserCase implements Comparable { return -object.getLastAccessedDate().compareTo(otherObject.getLastAccessedDate()); } } + + /** + * Exception thrown when there is a problem creating a multi-user case. + */ + final static 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); + } + } enum CaseStatus { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java index ec3b42116d..3101461443 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java @@ -78,7 +78,11 @@ final class MultiUserCaseManager { if(caseFolder.exists()) { File[] autFiles = caseFolder.listFiles((dir, name) -> name.toLowerCase().endsWith(".aut")); if(autFiles != null && autFiles.length > 0) { + try { cases.add(new MultiUserCase(casePath)); + } catch (CaseMetadata.CaseMetadataException | MultiUserCase.MultiUserCaseException ex) { + // Ignore and continue. + } } } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.form deleted file mode 100755 index a54439c4d3..0000000000 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.form +++ /dev/null @@ -1,230 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.java deleted file mode 100755 index 5f3365e8b1..0000000000 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasePanel.java +++ /dev/null @@ -1,562 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011-2017 Basis Technology Corp. - * Contact: carrier sleuthkit 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.Cursor; -import java.awt.Desktop; -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Date; -import java.util.List; -import java.util.logging.Level; -import javax.swing.JOptionPane; -import javax.swing.event.ListSelectionEvent; -import javax.swing.table.DefaultTableModel; -import javax.swing.table.TableColumn; -import org.sleuthkit.autopsy.coreutils.CaseStatusIconCellRenderer; -import org.sleuthkit.autopsy.coreutils.GrayableCellRenderer; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.LongDateCellRenderer; -import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; - -/** - * A panel that allows a user to open cases created by auto ingest. - */ -public class MultiUserCasePanel extends javax.swing.JPanel { - - private static final long serialVersionUID = 1L; - private static final Logger LOGGER = Logger.getLogger(MultiUserCasePanel.class.getName()); - private static final String LOG_FILE_NAME = "auto_ingest_log.txt"; - private static final MultiUserCase.LastAccessedDateDescendingComparator REVERSE_DATE_MODIFIED_COMPARATOR = new 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; - private static final int TIME_COL_MIN_WIDTH = 40; - private static final int TIME_COL_MAX_WIDTH = 250; - private static final int TIME_COL_PREFERRED_WIDTH = 160; - 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; - - /* - * The JTable table model for the cases table presented by this view is - * defined by the following string, enum, and array. - * - * 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(MultiUserCasePanel.class, "ReviewModeCasePanel.CaseHeaderText"); - private static final String CREATEDTIME_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "ReviewModeCasePanel.CreatedTimeHeaderText"); - private static final String COMPLETEDTIME_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "ReviewModeCasePanel.LastAccessedTimeHeaderText"); - private static final String STATUS_ICON_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "ReviewModeCasePanel.StatusIconHeaderText"); - private static final String OUTPUT_FOLDER_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "ReviewModeCasePanel.OutputFolderHeaderText"); - - enum COLUMN_HEADERS { - - CASE, - CREATEDTIME, - COMPLETEDTIME, - STATUS_ICON, - OUTPUTFOLDER - } - private final String[] columnNames = {CASE_HEADER, CREATEDTIME_HEADER, COMPLETEDTIME_HEADER, STATUS_ICON_HEADER, OUTPUT_FOLDER_HEADER}; - private DefaultTableModel caseTableModel; - private Path currentlySelectedCase = null; - - /** - * Constructs a panel that allows a user to open cases created by automated - * ingest. - * - * @param parent The parent dialog for this panel. - */ - MultiUserCasePanel() { - caseTableModel = new DefaultTableModel(columnNames, 0) { - private static final long serialVersionUID = 1L; - - @Override - 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)) { - return Date.class; - } else { - return super.getColumnClass(col); - } - } - }; - - initComponents(); - - /* - * Configure the columns of the cases table. - */ - TableColumn theColumn; - theColumn = casesTable.getColumn(CASE_HEADER); - theColumn.setCellRenderer(new GrayableCellRenderer()); - theColumn.setMinWidth(CASE_COL_MIN_WIDTH); - theColumn.setMaxWidth(CASE_COL_MAX_WIDTH); - theColumn.setPreferredWidth(CASE_COL_PREFERRED_WIDTH); - theColumn.setWidth(CASE_COL_PREFERRED_WIDTH); - - theColumn = casesTable.getColumn(CREATEDTIME_HEADER); - theColumn.setCellRenderer(new LongDateCellRenderer()); - theColumn.setMinWidth(TIME_COL_MIN_WIDTH); - theColumn.setMaxWidth(TIME_COL_MAX_WIDTH); - theColumn.setPreferredWidth(TIME_COL_PREFERRED_WIDTH); - theColumn.setWidth(TIME_COL_PREFERRED_WIDTH); - - theColumn = casesTable.getColumn(COMPLETEDTIME_HEADER); - theColumn.setCellRenderer(new LongDateCellRenderer()); - theColumn.setMinWidth(TIME_COL_MIN_WIDTH); - theColumn.setMaxWidth(TIME_COL_MAX_WIDTH); - theColumn.setPreferredWidth(TIME_COL_PREFERRED_WIDTH); - theColumn.setWidth(TIME_COL_PREFERRED_WIDTH); - - theColumn = casesTable.getColumn(STATUS_ICON_HEADER); - theColumn.setCellRenderer(new CaseStatusIconCellRenderer()); - 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)); - - /* - * Listen for row selection changes and set button state for the current - * selection. - */ - casesTable.getSelectionModel().addListSelectionListener((ListSelectionEvent e) -> { - //Ignore extra messages. - if (e.getValueIsAdjusting()) { - return; - } - setButtons(); - }); - refreshCasesTable(); - } - - /** - * Gets the list of cases known to the review mode cases manager and - * refreshes the cases table. - */ - private void refreshCasesTable() { - try { - currentlySelectedCase = getSelectedCase(); - MultiUserCaseManager manager = MultiUserCaseManager.getInstance(); - List 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.getCaseName(), - autoIngestCase.getCreationDate(), - autoIngestCase.getLastAccessedDate(), - (MultiUserCase.CaseStatus.OK != autoIngestCase.getStatus()), - autoIngestCase.getCaseDirectoryPath().toString()}); - } - } - setSelectedCase(currentlySelectedCase); - setButtons(); - } catch (Exception ex) { - LOGGER.log(Level.SEVERE, "Unexpected exception in refreshCasesTable", ex); //NON-NLS - } - } - - /** - * Gets the current selection in the cases table. - * - * @return A path representing the current selected case, null if there is - * no selection. - */ - private Path getSelectedCase() { - try { - int selectedRow = casesTable.getSelectedRow(); - if (selectedRow >= 0 && selectedRow < casesTable.getRowCount()) { - return Paths.get(caseTableModel.getValueAt(casesTable.convertRowIndexToModel(selectedRow), COLUMN_HEADERS.CASE.ordinal()).toString()); - } - } catch (Exception ignored) { - return null; - } - return null; - } - - /** - * Sets the current selection in the cases table. - * - * @param path The case folder path of the case to select. - */ - private void setSelectedCase(Path path) { - if (path != null) { - try { - for (int row = 0; row < casesTable.getRowCount(); ++row) { - Path temp = Paths.get(caseTableModel.getValueAt(casesTable.convertRowIndexToModel(row), COLUMN_HEADERS.CASE.ordinal()).toString()); - if (temp.compareTo(path) == 0) { // found it - casesTable.setRowSelectionInterval(row, row); - return; - } - } - } catch (Exception ignored) { - casesTable.clearSelection(); - } - } - casesTable.clearSelection(); - } - - /** - * Enables/disables the Open and Show Log buttons based on the case selected - * in the cases table. - */ - private void setButtons() { - 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); - } - - /** - * 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 thePath = (String) caseTableModel.getValueAt(casesTable.convertRowIndexToModel(selectedRow), COLUMN_HEADERS.OUTPUTFOLDER.ordinal()); - retValue = Paths.get(thePath, LOG_FILE_NAME); - } - - return retValue; - } - - /** - * Opens a case. - * - * @param caseMetadataFilePath The path to the case metadata file. - */ - private void openCase(Path caseMetadataFilePath) { - setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - try { - StartupWindowProvider.getInstance().close(); - CueBannerPanel.closeMultiUserCasesWindow(); - CaseOpenMultiUserAction.closeMultiUserCasesWindow(); - 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()); - } - StartupWindowProvider.getInstance().open(); - } finally { - setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } - } - - /** - * 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); - } - - /** - * 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") - // //GEN-BEGIN:initComponents - private void initComponents() { - - rbGroupHistoryLength = new javax.swing.ButtonGroup(); - bnOpen = new javax.swing.JButton(); - scrollPaneTable = new javax.swing.JScrollPane(); - casesTable = new javax.swing.JTable(); - bnRefresh = new javax.swing.JButton(); - panelFilter = new javax.swing.JPanel(); - rbAllCases = new javax.swing.JRadioButton(); - bnShowLog = new javax.swing.JButton(); - rbDays = new javax.swing.JRadioButton(); - rbWeeks = new javax.swing.JRadioButton(); - rbMonths = new javax.swing.JRadioButton(); - rbGroupLabel = new javax.swing.JLabel(); - - setName("Completed Cases"); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(bnOpen, org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "MultiUserCasePanel.bnOpen.text")); // NOI18N - bnOpen.setEnabled(false); - bnOpen.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - bnOpenActionPerformed(evt); - } - }); - - 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() { - public void mouseClicked(java.awt.event.MouseEvent evt) { - casesTableMouseClicked(evt); - } - }); - scrollPaneTable.setViewportView(casesTable); - - org.openide.awt.Mnemonics.setLocalizedText(bnRefresh, org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "MultiUserCasePanel.bnRefresh.text")); // NOI18N - bnRefresh.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - bnRefreshActionPerformed(evt); - } - }); - - rbGroupHistoryLength.add(rbAllCases); - rbAllCases.setSelected(true); - org.openide.awt.Mnemonics.setLocalizedText(rbAllCases, org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "MultiUserCasePanel.rbAllCases.text")); // NOI18N - rbAllCases.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - rbAllCasesItemStateChanged(evt); - } - }); - - javax.swing.GroupLayout panelFilterLayout = new javax.swing.GroupLayout(panelFilter); - panelFilter.setLayout(panelFilterLayout); - panelFilterLayout.setHorizontalGroup( - panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(panelFilterLayout.createSequentialGroup() - .addComponent(rbAllCases) - .addGap(0, 0, Short.MAX_VALUE)) - ); - panelFilterLayout.setVerticalGroup( - panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelFilterLayout.createSequentialGroup() - .addGap(0, 0, 0) - .addComponent(rbAllCases)) - ); - - org.openide.awt.Mnemonics.setLocalizedText(bnShowLog, org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "MultiUserCasePanel.bnShowLog.text")); // NOI18N - bnShowLog.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "MultiUserCasePanel.bnShowLog.toolTipText")); // NOI18N - bnShowLog.setEnabled(false); - bnShowLog.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - bnShowLogActionPerformed(evt); - } - }); - - rbGroupHistoryLength.add(rbDays); - org.openide.awt.Mnemonics.setLocalizedText(rbDays, org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "MultiUserCasePanel.rbDays.text")); // NOI18N - rbDays.setName(""); // NOI18N - rbDays.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - rbDaysItemStateChanged(evt); - } - }); - - rbGroupHistoryLength.add(rbWeeks); - org.openide.awt.Mnemonics.setLocalizedText(rbWeeks, org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "MultiUserCasePanel.rbWeeks.text")); // NOI18N - rbWeeks.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - rbWeeksItemStateChanged(evt); - } - }); - - rbGroupHistoryLength.add(rbMonths); - org.openide.awt.Mnemonics.setLocalizedText(rbMonths, org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "MultiUserCasePanel.rbMonths.text")); // NOI18N - rbMonths.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - rbMonthsItemStateChanged(evt); - } - }); - - rbGroupLabel.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(rbGroupLabel, org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "MultiUserCasePanel.rbGroupLabel.text")); // NOI18N - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(4, 4, 4) - .addComponent(bnOpen, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(bnShowLog) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(rbGroupLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(rbDays) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(rbWeeks) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(rbMonths) - .addGap(0, 0, 0) - .addComponent(panelFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(bnRefresh) - .addGap(4, 4, 4)) - .addComponent(scrollPaneTable)) - .addContainerGap()) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(6, 6, 6) - .addComponent(scrollPaneTable, javax.swing.GroupLayout.PREFERRED_SIZE, 450, 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(bnOpen) - .addComponent(bnShowLog)) - .addComponent(bnRefresh) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(rbDays) - .addComponent(rbWeeks) - .addComponent(rbMonths) - .addComponent(rbGroupLabel)) - .addComponent(panelFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) - .addGap(0, 0, 0)) - ); - }// //GEN-END:initComponents - - /** - * Open button action - * - * @param evt -- The event that caused this to be called - */ - 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()); - - new Thread(() -> { - openCase(caseMetadataFilePath); - }).start(); - }//GEN-LAST:event_bnOpenActionPerformed - - /** - * Refresh button action - * - * @param evt -- The event that caused this to be called - */ - private void bnRefreshActionPerformed(java.awt.event.ActionEvent evt) { - refreshCasesTable(); - } - - private void rbDaysItemStateChanged(java.awt.event.ItemEvent evt) { - if (rbDays.isSelected()) { - refreshCasesTable(); - } - } - - private void rbAllCasesItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbAllCasesItemStateChanged - if (rbAllCases.isSelected()) { - refreshCasesTable(); - } - }//GEN-LAST:event_rbAllCasesItemStateChanged - - private void rbMonthsItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbMonthsItemStateChanged - if (rbMonths.isSelected()) { - refreshCasesTable(); - } - }//GEN-LAST:event_rbMonthsItemStateChanged - - private void rbWeeksItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbWeeksItemStateChanged - if (rbWeeks.isSelected()) { - refreshCasesTable(); - } - }//GEN-LAST:event_rbWeeksItemStateChanged - - private void bnShowLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnShowLogActionPerformed - 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(MultiUserCasePanel.class, "DisplayLogDialog.cannotFindLog"), - org.openide.util.NbBundle.getMessage(MultiUserCasePanel.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); - JOptionPane.showMessageDialog(this, - org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "DisplayLogDialog.cannotOpenLog"), - org.openide.util.NbBundle.getMessage(MultiUserCasePanel.class, "DisplayLogDialog.unableToShowLogFile"), - JOptionPane.PLAIN_MESSAGE); - } - } - }//GEN-LAST:event_bnShowLogActionPerformed - - 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()); - openCase(caseMetadataFilePath); - } - }//GEN-LAST:event_casesTableMouseClicked - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton bnOpen; - private javax.swing.JButton bnRefresh; - private javax.swing.JButton bnShowLog; - private javax.swing.JTable casesTable; - private javax.swing.JPanel panelFilter; - private javax.swing.JRadioButton rbAllCases; - private javax.swing.JRadioButton rbDays; - private javax.swing.ButtonGroup rbGroupHistoryLength; - private javax.swing.JLabel rbGroupLabel; - private javax.swing.JRadioButton rbMonths; - private javax.swing.JRadioButton rbWeeks; - private javax.swing.JScrollPane scrollPaneTable; - // End of variables declaration//GEN-END:variables - -} diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java old mode 100644 new mode 100755 diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java old mode 100644 new mode 100755 diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java old mode 100644 new mode 100755 diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java old mode 100644 new mode 100755 diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java old mode 100644 new mode 100755 diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java old mode 100644 new mode 100755 diff --git a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java index df63b0fa1f..0e7fc3da5e 100755 --- a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java +++ b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014 Basis Technology Corp. + * Copyright 2014-2017 Basis Technology Corp. * Contact: carrier sleuthkit 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; @@ -77,7 +76,6 @@ public final class UserPreferences { STANDALONE, AUTOINGEST, - REVIEW }; /** diff --git a/Core/src/org/sleuthkit/autopsy/core/timelineWsmode.xml b/Core/src/org/sleuthkit/autopsy/core/timelineWsmode.xml old mode 100644 new mode 100755 diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java b/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java index c908f3b35d..060061e205 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java @@ -30,7 +30,10 @@ import org.netbeans.swing.tabcontrol.plaf.DefaultTabbedContainerUI; import org.openide.modules.ModuleInstall; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.StartupWindowProvider; +import org.sleuthkit.autopsy.core.UserPreferences; +import static org.sleuthkit.autopsy.core.UserPreferences.SETTINGS_PROPERTIES; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.ModuleSettings; /** * Manages this module's life cycle. Opens the startup dialog during startup. @@ -59,6 +62,7 @@ public class Installer extends ModuleInstall { UIManager.put("ViewTabDisplayerUI", "org.sleuthkit.autopsy.corecomponents.NoTabsTabDisplayerUI"); UIManager.put(DefaultTabbedContainerUI.KEY_VIEW_CONTENT_BORDER, BorderFactory.createEmptyBorder()); UIManager.put("TabbedPane.contentBorderInsets", new Insets(0, 0, 0, 0)); + updateConfig(); WindowManager.getDefault().invokeWhenUIReady(() -> { StartupWindowProvider.getInstance().open(); }); @@ -68,6 +72,21 @@ public class Installer extends ModuleInstall { public void uninstalled() { super.uninstalled(); } + + /** + * 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)); + } + } + } private void setLookAndFeel() { if (System.getProperty("os.name").toLowerCase().contains("mac")) { //NON-NLS diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/FileSystemDetailsAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/FileSystemDetailsAction.java old mode 100644 new mode 100755 diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseOpenAction.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseOpenAction.java index 265190663e..6a84946c91 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseOpenAction.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseOpenAction.java @@ -53,7 +53,6 @@ final class AutoIngestCaseOpenAction extends CallableSystemAction implements Act break; case STANDALONE: - case REVIEW: /** * In standalone mode, invoke default Autopsy version of CaseOpenAction. */ diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.form b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.form index 4a943b4924..9a599877f8 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.form +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.form @@ -29,8 +29,19 @@ + + - + + + + + + + + + + @@ -39,18 +50,9 @@ - - - - - - - - - @@ -81,6 +83,7 @@ + @@ -255,5 +258,15 @@ + + + + + + + + + + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java index 5537d07236..38b408de9f 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java @@ -664,6 +664,7 @@ 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 @@ -764,6 +765,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( @@ -772,24 +780,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( @@ -815,7 +825,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()) ); }// //GEN-END:initComponents @@ -874,7 +885,12 @@ public final class AutoIngestDashboard extends JPanel implements Observer { } }//GEN-LAST:event_prioritizeCaseButtonActionPerformed + private void clusterMetricsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_clusterMetricsButtonActionPerformed + new AutoIngestMetricsDialog(this.getTopLevelAncestor(), autoIngestMonitor); + }//GEN-LAST:event_clusterMetricsButtonActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton clusterMetricsButton; private javax.swing.JScrollPane completedScrollPane; private javax.swing.JTable completedTable; private javax.swing.JButton jButton1; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboardOpenAction.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboardOpenAction.java index 10ff60da2a..45563a4f4b 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboardOpenAction.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboardOpenAction.java @@ -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") diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java index 9a262bb6d3..09f0c7c949 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java @@ -23,10 +23,12 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Observable; import java.util.Set; +import java.util.TreeSet; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.logging.Level; @@ -265,17 +267,94 @@ 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(); } } + /** + * Gets a new metrics snapshot from the coordination service for an auto + * ingest cluster. The jobs snapshot will also be updated. + * + * @return The metrics snapshot. + */ + private MetricsSnapshot queryCoordinationServiceForMetrics() { + try { + JobsSnapshot newJobsSnapshot = new JobsSnapshot(); + MetricsSnapshot newMetricsSnapshot = new MetricsSnapshot(); + List nodeList = coordinationService.getNodeList(CoordinationService.CategoryNode.MANIFESTS); + for (String node : nodeList) { + try { + AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, node)); + if (nodeData.getVersion() < 1) { + /* + * Ignore version '0' nodes that have not been + * "upgraded" since they don't carry enough data. + */ + continue; + } + AutoIngestJob job = new AutoIngestJob(nodeData); + ProcessingStatus processingStatus = nodeData.getProcessingStatus(); + switch (processingStatus) { + case PENDING: + newJobsSnapshot.addOrReplacePendingJob(job); + break; + case PROCESSING: + newJobsSnapshot.addOrReplaceRunningJob(job); + break; + case COMPLETED: + newJobsSnapshot.addOrReplaceCompletedJob(job); + newMetricsSnapshot.addCompletedJobDate(job.getCompletedDate()); + break; + case DELETED: + break; + default: + LOGGER.log(Level.SEVERE, "Unknown AutoIngestJobData.ProcessingStatus"); + break; + } + } catch (InterruptedException ex) { + LOGGER.log(Level.SEVERE, String.format("Unexpected interrupt while retrieving coordination service node data for '%s'", node), ex); + } catch (AutoIngestJobNodeData.InvalidDataException ex) { + LOGGER.log(Level.SEVERE, String.format("Unable to use node data for '%s'", node), ex); + } catch (AutoIngestJob.AutoIngestJobException ex) { + LOGGER.log(Level.SEVERE, String.format("Failed to create a job for '%s'", node), ex); + } + } + + return newMetricsSnapshot; + + } catch (CoordinationServiceException ex) { + LOGGER.log(Level.SEVERE, "Failed to get node list from coordination service", ex); + return new MetricsSnapshot(); + } + } + + /** + * Gets a new metrics snapshot. The jobs snapshot will also be updated in + * effect. + * + * @return The metrics snapshot. + */ + public MetricsSnapshot getMetricsSnapshot() { + MetricsSnapshot metricsSnapshot; + + synchronized (jobsLock) { + metricsSnapshot = queryCoordinationServiceForMetrics(); + } + + return metricsSnapshot; + } + /** * Bumps the priority of all pending ingest jobs for a specified case. * @@ -522,6 +601,32 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang } + /** + * A snapshot of metrics for an auto ingest cluster. + */ + public static final class MetricsSnapshot { + + private final List completedJobDates = new ArrayList<>(); + + /** + * Gets a list of completed job dates, formatted in milliseconds. + * + * @return The completed job dates, formatted in milliseconds. + */ + List getCompletedJobDates() { + return new ArrayList<>(completedJobDates); + } + + /** + * Adds a new date to the list of completed job dates. + * + * @param date The date to be added. + */ + void addCompletedJobDate(Date date) { + completedJobDates.add(date.getTime()); + } + } + /** * Exception type thrown when there is an error completing an auto ingest * monitor operation. diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties index fc80df5551..c856dbe8bf 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties @@ -227,3 +227,8 @@ 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 diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CaseImportPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CaseImportPanel.java index a7cd13af72..2e4866b010 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CaseImportPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CaseImportPanel.java @@ -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() diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/dashboardWsmode.xml b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/dashboardWsmode.xml old mode 100644 new mode 100755 diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryWsmode.xml b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryWsmode.xml old mode 100644 new mode 100755 diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/layer.xml b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/layer.xml old mode 100644 new mode 100755 diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/CreditCardValidator.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/CreditCardValidator.java old mode 100644 new mode 100755 diff --git a/KeywordSearch/test/unit/src/org/sleuthkit/autopsy/keywordsearch/CreditCardValidatorTest.java b/KeywordSearch/test/unit/src/org/sleuthkit/autopsy/keywordsearch/CreditCardValidatorTest.java old mode 100644 new mode 100755 diff --git a/docs/doxygen-user/central_repo.dox b/docs/doxygen-user/central_repo.dox old mode 100644 new mode 100755 diff --git a/docs/doxygen-user/images/central_repo_content_viewer.png b/docs/doxygen-user/images/central_repo_content_viewer.png old mode 100644 new mode 100755 diff --git a/docs/doxygen-user/images/central_repo_interesting_items.png b/docs/doxygen-user/images/central_repo_interesting_items.png old mode 100644 new mode 100755 diff --git a/docs/doxygen-user/images/central_repo_manage_tags.png b/docs/doxygen-user/images/central_repo_manage_tags.png old mode 100644 new mode 100755 diff --git a/docs/doxygen-user/images/central_repo_options.png b/docs/doxygen-user/images/central_repo_options.png old mode 100644 new mode 100755 diff --git a/docs/doxygen-user/images/central_repo_postgres.png b/docs/doxygen-user/images/central_repo_postgres.png old mode 100644 new mode 100755 diff --git a/docs/doxygen-user/images/central_repo_sqlite.png b/docs/doxygen-user/images/central_repo_sqlite.png old mode 100644 new mode 100755 diff --git a/docs/doxygen-user/images/central_repo_tag_file.png b/docs/doxygen-user/images/central_repo_tag_file.png old mode 100644 new mode 100755 diff --git a/docs/doxygen-user/images/central_repo_types.png b/docs/doxygen-user/images/central_repo_types.png old mode 100644 new mode 100755 diff --git a/docs/doxygen-user/images/email_datasource_tree.png b/docs/doxygen-user/images/email_datasource_tree.png old mode 100644 new mode 100755 diff --git a/docs/doxygen-user/images/messages_datasource_tree.png b/docs/doxygen-user/images/messages_datasource_tree.png old mode 100644 new mode 100755 diff --git a/ruleset.xml b/ruleset.xml old mode 100644 new mode 100755 From 59afda83c67249d4af11fc32b0ac8f763f7eef63 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 3 Nov 2017 15:12:38 -0400 Subject: [PATCH 35/69] Additional files for auto ingest metrics feature --- .../casemodule/MultiUserCasesDialog.java | 81 +++ .../casemodule/MultiUserCasesPanel.form | 230 +++++++ .../casemodule/MultiUserCasesPanel.java | 582 ++++++++++++++++++ .../autoingest/AutoIngestMetricsDialog.form | 113 ++++ .../autoingest/AutoIngestMetricsDialog.java | 178 ++++++ 5 files changed, 1184 insertions(+) create mode 100755 Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesDialog.java create mode 100755 Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form create mode 100755 Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java create mode 100755 Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.form create mode 100755 Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesDialog.java new file mode 100755 index 0000000000..b6d9feeb7e --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesDialog.java @@ -0,0 +1,81 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2017 Basis Technology Corp. + * Contact: carrier sleuthkit 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. + */ +public class MultiUserCasesDialog extends JDialog { + private static final String REVIEW_MODE_TITLE = "Open Multi-User Case"; + private final 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(); + } + return instance; + } + + /** + * Constructs a MultiUserCasesDialog object. + */ + MultiUserCasesDialog() { + super(WindowManager.getDefault().getMainWindow(), + REVIEW_MODE_TITLE, + Dialog.ModalityType.APPLICATION_MODAL); + + getRootPane().registerKeyboardAction( + e -> { + setVisible(false); + }, + KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW); + + multiUserCasesPanel = new MultiUserCasesPanel(); + 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.refreshCasesTable(); + } + super.setVisible(value); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form new file mode 100755 index 0000000000..179bc23bb8 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form @@ -0,0 +1,230 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java new file mode 100755 index 0000000000..d905f36c2c --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java @@ -0,0 +1,582 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2017 Basis Technology Corp. + * Contact: carrier sleuthkit 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.Cursor; +import java.awt.Desktop; +import java.awt.EventQueue; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Date; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.logging.Level; +import javax.swing.JOptionPane; +import javax.swing.SwingWorker; +import javax.swing.event.ListSelectionEvent; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableColumn; +import org.sleuthkit.autopsy.coreutils.CaseStatusIconCellRenderer; +import org.sleuthkit.autopsy.coreutils.GrayableCellRenderer; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.LongDateCellRenderer; +import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; + +/** + * A panel that allows a user to open cases created by auto ingest. + */ +public class MultiUserCasesPanel extends javax.swing.JPanel { + + private static final long serialVersionUID = 1L; + private static final Logger LOGGER = Logger.getLogger(MultiUserCasesPanel.class.getName()); + private static final String LOG_FILE_NAME = "auto_ingest_log.txt"; + private static final MultiUserCase.LastAccessedDateDescendingComparator REVERSE_DATE_MODIFIED_COMPARATOR = new 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; + private static final int TIME_COL_MIN_WIDTH = 40; + private static final int TIME_COL_MAX_WIDTH = 250; + private static final int TIME_COL_PREFERRED_WIDTH = 160; + 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; + + /* + * The JTable table model for the cases table presented by this view is + * defined by the following string, enum, and array. + * + * 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(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"); + + enum COLUMN_HEADERS { + + CASE, + CREATEDTIME, + COMPLETEDTIME, + STATUS_ICON, + OUTPUTFOLDER + } + private final String[] columnNames = {CASE_HEADER, CREATEDTIME_HEADER, COMPLETEDTIME_HEADER, STATUS_ICON_HEADER, OUTPUT_FOLDER_HEADER}; + private DefaultTableModel caseTableModel; + private Path currentlySelectedCase = null; + + /** + * Constructs a panel that allows a user to open cases created by automated + * ingest. + */ + MultiUserCasesPanel() { + caseTableModel = new DefaultTableModel(columnNames, 0) { + private static final long serialVersionUID = 1L; + + @Override + 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)) { + return Date.class; + } else { + return super.getColumnClass(col); + } + } + }; + + initComponents(); + + /* + * Configure the columns of the cases table. + */ + TableColumn theColumn; + theColumn = casesTable.getColumn(CASE_HEADER); + theColumn.setCellRenderer(new GrayableCellRenderer()); + theColumn.setMinWidth(CASE_COL_MIN_WIDTH); + theColumn.setMaxWidth(CASE_COL_MAX_WIDTH); + theColumn.setPreferredWidth(CASE_COL_PREFERRED_WIDTH); + theColumn.setWidth(CASE_COL_PREFERRED_WIDTH); + + theColumn = casesTable.getColumn(CREATEDTIME_HEADER); + theColumn.setCellRenderer(new LongDateCellRenderer()); + theColumn.setMinWidth(TIME_COL_MIN_WIDTH); + theColumn.setMaxWidth(TIME_COL_MAX_WIDTH); + theColumn.setPreferredWidth(TIME_COL_PREFERRED_WIDTH); + theColumn.setWidth(TIME_COL_PREFERRED_WIDTH); + + theColumn = casesTable.getColumn(COMPLETEDTIME_HEADER); + theColumn.setCellRenderer(new LongDateCellRenderer()); + theColumn.setMinWidth(TIME_COL_MIN_WIDTH); + theColumn.setMaxWidth(TIME_COL_MAX_WIDTH); + theColumn.setPreferredWidth(TIME_COL_PREFERRED_WIDTH); + theColumn.setWidth(TIME_COL_PREFERRED_WIDTH); + + theColumn = casesTable.getColumn(STATUS_ICON_HEADER); + theColumn.setCellRenderer(new CaseStatusIconCellRenderer()); + 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)); + + /* + * Listen for row selection changes and set button state for the current + * selection. + */ + casesTable.getSelectionModel().addListSelectionListener((ListSelectionEvent e) -> { + //Ignore extra messages. + if (e.getValueIsAdjusting()) { + return; + } + setButtons(); + }); + } + + /** + * Gets the list of cases known to the review mode cases manager and + * refreshes the cases table. + */ + void refreshCasesTable() { + EventQueue.invokeLater(() -> { + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + }); + + new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { + try { + currentlySelectedCase = getSelectedCase(); + MultiUserCaseManager manager = MultiUserCaseManager.getInstance(); + List 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.getCaseName(), + autoIngestCase.getCreationDate(), + autoIngestCase.getLastAccessedDate(), + (MultiUserCase.CaseStatus.OK != autoIngestCase.getStatus()), + autoIngestCase.getMetadataFilePath().toString()}); + } + } + setSelectedCase(currentlySelectedCase); + setButtons(); + } catch (Exception ex) { + LOGGER.log(Level.SEVERE, "Unexpected exception while refreshing the table.", ex); //NON-NLS + } + return null; + } + + @Override + protected void done() { + super.done(); + setCursor(null); + try { + get(); + } catch (InterruptedException | ExecutionException ex) { + LOGGER.log(Level.SEVERE, "Unexpected exception while refreshing the table.", ex); //NON-NLS + } + } + }.execute(); + } + + /** + * Gets the current selection in the cases table. + * + * @return A path representing the current selected case, null if there is + * no selection. + */ + private Path getSelectedCase() { + try { + int selectedRow = casesTable.getSelectedRow(); + if (selectedRow >= 0 && selectedRow < casesTable.getRowCount()) { + return Paths.get(caseTableModel.getValueAt(casesTable.convertRowIndexToModel(selectedRow), COLUMN_HEADERS.CASE.ordinal()).toString()); + } + } catch (Exception ignored) { + return null; + } + return null; + } + + /** + * Sets the current selection in the cases table. + * + * @param path The case folder path of the case to select. + */ + private void setSelectedCase(Path path) { + if (path != null) { + try { + for (int row = 0; row < casesTable.getRowCount(); ++row) { + Path temp = Paths.get(caseTableModel.getValueAt(casesTable.convertRowIndexToModel(row), COLUMN_HEADERS.CASE.ordinal()).toString()); + if (temp.compareTo(path) == 0) { // found it + casesTable.setRowSelectionInterval(row, row); + return; + } + } + } catch (Exception ignored) { + casesTable.clearSelection(); + } + } + casesTable.clearSelection(); + } + + /** + * Enables/disables the Open and Show Log buttons based on the case selected + * in the cases table. + */ + private void setButtons() { + 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); + } + + /** + * 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 thePath = (String) caseTableModel.getValueAt(casesTable.convertRowIndexToModel(selectedRow), COLUMN_HEADERS.OUTPUTFOLDER.ordinal()); + retValue = Paths.get(thePath, LOG_FILE_NAME); + } + + return retValue; + } + + /** + * Opens a case. + * + * @param caseMetadataFilePath The path to the case metadata file. + */ + private void openCase(Path caseMetadataFilePath) { + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + try { + StartupWindowProvider.getInstance().close(); + CueBannerPanel.closeMultiUserCasesWindow(); + CaseOpenMultiUserAction.closeMultiUserCasesWindow(); + 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()); + } + StartupWindowProvider.getInstance().open(); + } finally { + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + } + + /** + * 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); + } + + /** + * 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") + // //GEN-BEGIN:initComponents + private void initComponents() { + + rbGroupHistoryLength = new javax.swing.ButtonGroup(); + bnOpen = new javax.swing.JButton(); + scrollPaneTable = new javax.swing.JScrollPane(); + casesTable = new javax.swing.JTable(); + bnRefresh = new javax.swing.JButton(); + panelFilter = new javax.swing.JPanel(); + rbAllCases = new javax.swing.JRadioButton(); + bnShowLog = new javax.swing.JButton(); + rbDays = new javax.swing.JRadioButton(); + rbWeeks = new javax.swing.JRadioButton(); + rbMonths = new javax.swing.JRadioButton(); + rbGroupLabel = new javax.swing.JLabel(); + + setName("Completed Cases"); // 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) { + bnOpenActionPerformed(evt); + } + }); + + 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() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + casesTableMouseClicked(evt); + } + }); + scrollPaneTable.setViewportView(casesTable); + + 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); + } + }); + + rbGroupHistoryLength.add(rbAllCases); + rbAllCases.setSelected(true); + 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); + } + }); + + javax.swing.GroupLayout panelFilterLayout = new javax.swing.GroupLayout(panelFilter); + panelFilter.setLayout(panelFilterLayout); + panelFilterLayout.setHorizontalGroup( + panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelFilterLayout.createSequentialGroup() + .addComponent(rbAllCases) + .addGap(0, 0, Short.MAX_VALUE)) + ); + panelFilterLayout.setVerticalGroup( + panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelFilterLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addComponent(rbAllCases)) + ); + + 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) { + bnShowLogActionPerformed(evt); + } + }); + + rbGroupHistoryLength.add(rbDays); + 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) { + rbDaysItemStateChanged(evt); + } + }); + + rbGroupHistoryLength.add(rbWeeks); + 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); + } + }); + + rbGroupHistoryLength.add(rbMonths); + 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); + } + }); + + rbGroupLabel.setFont(new java.awt.Font("Tahoma", 0, 12)); // 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); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(4, 4, 4) + .addComponent(bnOpen, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(bnShowLog) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(rbGroupLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(rbDays) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(rbWeeks) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(rbMonths) + .addGap(0, 0, 0) + .addComponent(panelFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(bnRefresh) + .addGap(4, 4, 4)) + .addComponent(scrollPaneTable)) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(6, 6, 6) + .addComponent(scrollPaneTable, javax.swing.GroupLayout.PREFERRED_SIZE, 450, 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(bnOpen) + .addComponent(bnShowLog)) + .addComponent(bnRefresh) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(rbDays) + .addComponent(rbWeeks) + .addComponent(rbMonths) + .addComponent(rbGroupLabel)) + .addComponent(panelFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGap(0, 0, 0)) + ); + }// //GEN-END:initComponents + + /** + * Open button action + * + * @param evt -- The event that caused this to be called + */ + 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())); + + new Thread(() -> { + openCase(caseMetadataFilePath); + }).start(); + }//GEN-LAST:event_bnOpenActionPerformed + + /** + * Refresh button action + * + * @param evt -- The event that caused this to be called + */ + private void bnRefreshActionPerformed(java.awt.event.ActionEvent evt) { + refreshCasesTable(); + } + + private void rbDaysItemStateChanged(java.awt.event.ItemEvent evt) { + if (rbDays.isSelected()) { + refreshCasesTable(); + } + } + + private void rbAllCasesItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbAllCasesItemStateChanged + if (rbAllCases.isSelected()) { + refreshCasesTable(); + } + }//GEN-LAST:event_rbAllCasesItemStateChanged + + private void rbMonthsItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbMonthsItemStateChanged + if (rbMonths.isSelected()) { + refreshCasesTable(); + } + }//GEN-LAST:event_rbMonthsItemStateChanged + + private void rbWeeksItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbWeeksItemStateChanged + if (rbWeeks.isSelected()) { + refreshCasesTable(); + } + }//GEN-LAST:event_rbWeeksItemStateChanged + + private void bnShowLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnShowLogActionPerformed + 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(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); + JOptionPane.showMessageDialog(this, + org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.cannotOpenLog"), + org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.unableToShowLogFile"), + JOptionPane.PLAIN_MESSAGE); + } + } + }//GEN-LAST:event_bnShowLogActionPerformed + + 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())); + openCase(caseMetadataFilePath); + } + }//GEN-LAST:event_casesTableMouseClicked + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton bnOpen; + private javax.swing.JButton bnRefresh; + private javax.swing.JButton bnShowLog; + private javax.swing.JTable casesTable; + private javax.swing.JPanel panelFilter; + private javax.swing.JRadioButton rbAllCases; + private javax.swing.JRadioButton rbDays; + private javax.swing.ButtonGroup rbGroupHistoryLength; + private javax.swing.JLabel rbGroupLabel; + private javax.swing.JRadioButton rbMonths; + private javax.swing.JRadioButton rbWeeks; + private javax.swing.JScrollPane scrollPaneTable; + // End of variables declaration//GEN-END:variables + +} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.form b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.form new file mode 100755 index 0000000000..49e700ca21 --- /dev/null +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.form @@ -0,0 +1,113 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.java new file mode 100755 index 0000000000..5502bcb5d5 --- /dev/null +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.java @@ -0,0 +1,178 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2017 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.experimental.autoingest; + +import com.github.lgooddatepicker.datepicker.DatePicker; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Window; +import java.sql.Date; +import java.text.SimpleDateFormat; +import java.time.ZoneOffset; +import org.openide.util.NbBundle; +import org.openide.util.NbBundle.Messages; + +/** + * Display basic metrics for a cluster. + */ +public class AutoIngestMetricsDialog extends javax.swing.JDialog { + + private final AutoIngestMonitor autoIngestMonitor; + + /** + * Creates new form AutoIngestMetricsDialog + * + * @param parent The parent container. + * @param autoIngestMonitor The auto ingest monitor. + */ + @Messages({ + "AutoIngestMetricsDialog.title.text=Auto Ingest Cluster Metrics", + "AutoIngestMetricsDialog.initReportText=Select a date below and click the 'Get Metrics Since...' button to generate\na metrics report." + }) + public AutoIngestMetricsDialog(Container parent, AutoIngestMonitor autoIngestMonitor) { + super((Window) parent, NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.title.text"), ModalityType.MODELESS); + initComponents(); + reportTextArea.setText(NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.initReportText")); + this.autoIngestMonitor = autoIngestMonitor; + setModal(true); + setSize(getPreferredSize()); + setLocationRelativeTo(parent); + setVisible(true); + } + + /** + * Update the metrics shown in the report text area. + */ + private void updateMetrics() { + if(datePicker.getDate() == null) { + return; + } + + AutoIngestMonitor.MetricsSnapshot metricsSnapshot = autoIngestMonitor.getMetricsSnapshot(); + Object[] completedJobDates = metricsSnapshot.getCompletedJobDates().toArray(); + int count = 0; + long pickedDate = datePicker.getDate().atStartOfDay().toEpochSecond(ZoneOffset.UTC) * 1000; + for(int i = completedJobDates.length - 1; i >= 0; i--) { + if((Long)completedJobDates[i] >= pickedDate) { + count++; + } + } + + SimpleDateFormat dateFormatter = new SimpleDateFormat("MMM d, yyyy"); + reportTextArea.setText(String.format( + "Since %s:\n" + + "\tNumber of Jobs Completed: %d\n", + dateFormatter.format(Date.valueOf(datePicker.getDate())), + count + )); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //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(); + }// //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 +} From 9ae63a7d8d722c0ee871c02db2c8e5d83a533cc8 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 3 Nov 2017 17:01:55 -0400 Subject: [PATCH 36/69] Removed unnecessary method. --- .../sleuthkit/autopsy/casemodule/CaseMetadata.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java index 3757814aa9..6e47363db5 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java @@ -175,17 +175,6 @@ public final class CaseMetadata { public String getCaseDirectory() { return metadataFilePath.getParent().toString(); } - - /** - * Gets the full case directory path. - * - * @return The case directory path. - */ - public String getCaseDirectoryPath() { - String fileName = metadataFilePath.getFileName().toString(); - String caseDirectoryPath = metadataFilePath.toString(); - return caseDirectoryPath.substring(0, caseDirectoryPath.lastIndexOf(fileName)); - } /** * Gets the case type. From 0f0efd6ef0155e95739a8ad74f7df5e5094ba548 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 3 Nov 2017 17:03:55 -0400 Subject: [PATCH 37/69] Removed MultIuserCase class. --- .../autopsy/casemodule/MultiUserCase.java | 290 ------------------ 1 file changed, 290 deletions(-) delete mode 100755 Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java deleted file mode 100755 index 8ecc1c91e2..0000000000 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCase.java +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2015-2017 Basis Technology Corp. - * Contact: carrier sleuthkit 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.Comparator; -import java.util.Date; -import java.util.Objects; -import java.util.logging.Level; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.TimeStampUtils; - -/** - * A representation of a case created by automated ingest. - */ -class MultiUserCase implements Comparable { - - private static final Logger logger = Logger.getLogger(MultiUserCase.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. - * - * @throws CaseMetadata.CaseMetadataException If the CaseMetadata object - * cannot be constructed for the - * case display name. - * @throws MultiUserCaseException If no case metadata (.aut) - * file is found in the case - * directory. - */ - MultiUserCase(Path caseDirectoryPath) throws CaseMetadata.CaseMetadataException, MultiUserCaseException { - CaseMetadata caseMetadata = null; - - try { - caseMetadata = getCaseMetadataFromCaseDirectoryPath(caseDirectoryPath); - } catch (CaseMetadata.CaseMetadataException ex) { - logger.log(Level.SEVERE, String.format("Error reading the case metadata for %s.", caseDirectoryPath), ex); - throw ex; - } - - this.caseDirectoryPath = caseDirectoryPath; - caseName = caseMetadata.getCaseDisplayName(); - metadataFilePath = caseMetadata.getFilePath(); - 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 full path of the metadata (.aut) file. - * - * @return The metadata file path. - */ - Path getMetadataFilePath() { - return this.metadataFilePath; - } - - /** - * 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(caseDirectoryPath.resolve("autoingest.alert").toFile().exists()) { - return CaseStatus.ALERT; - } else { - return CaseStatus.OK; - } - } - - /** - * 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 static CaseMetadata getCaseMetadataFromCaseDirectoryPath(Path caseDirectoryPath) throws CaseMetadata.CaseMetadataException, MultiUserCaseException { - CaseMetadata caseMetadata = null; - - File directory = new File(caseDirectoryPath.toString()); - if (directory.isDirectory()) { - String fileNamePrefix = directory.getName(); - if (TimeStampUtils.endsWithTimeStamp(fileNamePrefix)) { - fileNamePrefix = fileNamePrefix.substring(0, fileNamePrefix.length() - TimeStampUtils.getTimeStampLength()); - } - - 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.caseName); - return hash; - } - - /** - * Compares this AutopIngestCase object with abnother 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 { - - /** - * Compares two MultiUserCase objects for order based on last accessed - * date (descending). - * - * @param object The first MultiUserCase 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(MultiUserCase object, MultiUserCase otherObject) { - return -object.getLastAccessedDate().compareTo(otherObject.getLastAccessedDate()); - } - } - - /** - * Exception thrown when there is a problem creating a multi-user case. - */ - final static 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); - } - } - - enum CaseStatus { - - OK, - ALERT - } - -} From e793197ec5ec0f2069418a23451725247ee790f5 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 3 Nov 2017 17:05:42 -0400 Subject: [PATCH 38/69] Fixed Java Doc text. --- .../org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java index 589b283d62..7e87ce8947 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java @@ -266,9 +266,9 @@ final class MultiUserCasesPanel extends javax.swing.JPanel { } /** - * Retrieves the log file path for the selected case in the cases table. + * Open a case. * - * @return The case log path. + * @param caseMetadataFilePath The path to the case metadata file. */ private void openCase(Path caseMetadataFilePath) { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); From 3fab3fdc8bc350d57640890cdc912115b544c233 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 3 Nov 2017 17:13:35 -0400 Subject: [PATCH 39/69] Rolled back Installer to previous content. --- .../autopsy/corecomponents/Installer.java | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java b/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java index 060061e205..c908f3b35d 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java @@ -30,10 +30,7 @@ import org.netbeans.swing.tabcontrol.plaf.DefaultTabbedContainerUI; import org.openide.modules.ModuleInstall; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.StartupWindowProvider; -import org.sleuthkit.autopsy.core.UserPreferences; -import static org.sleuthkit.autopsy.core.UserPreferences.SETTINGS_PROPERTIES; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.ModuleSettings; /** * Manages this module's life cycle. Opens the startup dialog during startup. @@ -62,7 +59,6 @@ public class Installer extends ModuleInstall { UIManager.put("ViewTabDisplayerUI", "org.sleuthkit.autopsy.corecomponents.NoTabsTabDisplayerUI"); UIManager.put(DefaultTabbedContainerUI.KEY_VIEW_CONTENT_BORDER, BorderFactory.createEmptyBorder()); UIManager.put("TabbedPane.contentBorderInsets", new Insets(0, 0, 0, 0)); - updateConfig(); WindowManager.getDefault().invokeWhenUIReady(() -> { StartupWindowProvider.getInstance().open(); }); @@ -72,21 +68,6 @@ public class Installer extends ModuleInstall { public void uninstalled() { super.uninstalled(); } - - /** - * 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)); - } - } - } private void setLookAndFeel() { if (System.getProperty("os.name").toLowerCase().contains("mac")) { //NON-NLS From 4bd750ef1039cc4618d23b7dc448fe95167c3851 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 3 Nov 2017 17:21:23 -0400 Subject: [PATCH 40/69] Permission change. --- .../autopsy/centralrepository/datamodel/AbstractSqlEamDb.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java old mode 100755 new mode 100644 From 1267234bb2715e53afdff48b1ffcf58856347a70 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 3 Nov 2017 17:24:30 -0400 Subject: [PATCH 41/69] Permissions change. --- .../org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java | 0 .../autopsy/centralrepository/datamodel/SqliteEamDb.java | 0 .../centralrepository/eventlisteners/CaseEventListener.java | 0 .../centralrepository/eventlisteners/IngestEventsListener.java | 0 .../autopsy/centralrepository/ingestmodule/IngestModule.java | 0 Core/src/org/sleuthkit/autopsy/core/timelineWsmode.xml | 0 .../sleuthkit/autopsy/directorytree/FileSystemDetailsAction.java | 0 7 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java mode change 100755 => 100644 Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java mode change 100755 => 100644 Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java mode change 100755 => 100644 Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java mode change 100755 => 100644 Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java mode change 100755 => 100644 Core/src/org/sleuthkit/autopsy/core/timelineWsmode.xml mode change 100755 => 100644 Core/src/org/sleuthkit/autopsy/directorytree/FileSystemDetailsAction.java diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java old mode 100755 new mode 100644 diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java old mode 100755 new mode 100644 diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java old mode 100755 new mode 100644 diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java old mode 100755 new mode 100644 diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java old mode 100755 new mode 100644 diff --git a/Core/src/org/sleuthkit/autopsy/core/timelineWsmode.xml b/Core/src/org/sleuthkit/autopsy/core/timelineWsmode.xml old mode 100755 new mode 100644 diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/FileSystemDetailsAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/FileSystemDetailsAction.java old mode 100755 new mode 100644 From d6af30faf22c6ae36bfaa3c3a073795661706e38 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 3 Nov 2017 17:28:14 -0400 Subject: [PATCH 42/69] Switched auto ingest metrics dialog from public. --- .../experimental/autoingest/AutoIngestMetricsDialog.java | 2 +- .../autopsy/experimental/autoingest/dashboardWsmode.xml | 0 2 files changed, 1 insertion(+), 1 deletion(-) mode change 100755 => 100644 Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/dashboardWsmode.xml diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.java index 5502bcb5d5..1acb72f005 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.java @@ -31,7 +31,7 @@ import org.openide.util.NbBundle.Messages; /** * Display basic metrics for a cluster. */ -public class AutoIngestMetricsDialog extends javax.swing.JDialog { +class AutoIngestMetricsDialog extends javax.swing.JDialog { private final AutoIngestMonitor autoIngestMonitor; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/dashboardWsmode.xml b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/dashboardWsmode.xml old mode 100755 new mode 100644 From 4c44a79477f97452b3ad276ffc0451744ac96412 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 3 Nov 2017 17:40:56 -0400 Subject: [PATCH 43/69] Minor revisions. --- .../autoingest/AutoIngestMetricsDialog.java | 4 ++-- .../experimental/autoingest/AutoIngestMonitor.java | 12 +++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.java index 1acb72f005..66c6d28581 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.java @@ -31,7 +31,7 @@ import org.openide.util.NbBundle.Messages; /** * Display basic metrics for a cluster. */ -class AutoIngestMetricsDialog extends javax.swing.JDialog { +final class AutoIngestMetricsDialog extends javax.swing.JDialog { private final AutoIngestMonitor autoIngestMonitor; @@ -45,7 +45,7 @@ class AutoIngestMetricsDialog extends javax.swing.JDialog { "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." }) - public AutoIngestMetricsDialog(Container parent, AutoIngestMonitor autoIngestMonitor) { + AutoIngestMetricsDialog(Container parent, AutoIngestMonitor autoIngestMonitor) { super((Window) parent, NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.title.text"), ModalityType.MODELESS); initComponents(); reportTextArea.setText(NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.initReportText")); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java index 09f0c7c949..02ad08e4ee 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java @@ -290,7 +290,6 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang */ private MetricsSnapshot queryCoordinationServiceForMetrics() { try { - JobsSnapshot newJobsSnapshot = new JobsSnapshot(); MetricsSnapshot newMetricsSnapshot = new MetricsSnapshot(); List nodeList = coordinationService.getNodeList(CoordinationService.CategoryNode.MANIFESTS); for (String node : nodeList) { @@ -307,17 +306,16 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang ProcessingStatus processingStatus = nodeData.getProcessingStatus(); switch (processingStatus) { case PENDING: - newJobsSnapshot.addOrReplacePendingJob(job); - break; case PROCESSING: - newJobsSnapshot.addOrReplaceRunningJob(job); + case DELETED: + /* + * These are not jobs we care about for metrics, so + * we will ignore them. + */ break; case COMPLETED: - newJobsSnapshot.addOrReplaceCompletedJob(job); newMetricsSnapshot.addCompletedJobDate(job.getCompletedDate()); break; - case DELETED: - break; default: LOGGER.log(Level.SEVERE, "Unknown AutoIngestJobData.ProcessingStatus"); break; From 06fa96f6cc3e817b2a764f9d71cfabd9de6361da Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 3 Nov 2017 17:43:12 -0400 Subject: [PATCH 44/69] Minor revision. --- .../autopsy/experimental/autoingest/AutoIngestMonitor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java index 02ad08e4ee..d6ec19d48b 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java @@ -284,7 +284,7 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang /** * Gets a new metrics snapshot from the coordination service for an auto - * ingest cluster. The jobs snapshot will also be updated. + * ingest cluster. * * @return The metrics snapshot. */ From 2bc4a03f0aa242e44aa3a30f6d8ddc79853dbd7f Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Fri, 3 Nov 2017 17:46:10 -0400 Subject: [PATCH 45/69] 3180: correct typo --- ...ntestFileFiltersTest.java => IngestFileFiltersTest.java} | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) rename Core/test/unit/src/org/sleuthkit/autopsy/ingest/{IntestFileFiltersTest.java => IngestFileFiltersTest.java} (88%) diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/ingest/IntestFileFiltersTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java similarity index 88% rename from Core/test/unit/src/org/sleuthkit/autopsy/ingest/IntestFileFiltersTest.java rename to Core/test/unit/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java index b952462de8..4dbec8bdc8 100755 --- a/Core/test/unit/src/org/sleuthkit/autopsy/ingest/IntestFileFiltersTest.java +++ b/Core/test/unit/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java @@ -22,10 +22,11 @@ import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.openide.modules.Places; -public class IntestFileFiltersTest { +public class IngestFileFiltersTest { - public IntestFileFiltersTest() { + public IngestFileFiltersTest() { } @BeforeClass @@ -46,6 +47,7 @@ public class IntestFileFiltersTest { @Test public void testFilters() { + Places.getUserDirectory().getAbsoluteFile(); System.out.println("Test filter"); } } From 21da396cf5eed08e3ee4487feb4994c8ff93181b Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 3 Nov 2017 18:03:13 -0400 Subject: [PATCH 46/69] Permission changes. --- .../experimental/autoingest/AutoIngestMonitor.java | 10 ++-------- .../autopsy/imagegallery/ImageGalleryWsmode.xml | 0 .../org/sleuthkit/autopsy/imagegallery/layer.xml | 0 .../autopsy/keywordsearch/CreditCardValidator.java | 0 .../keywordsearch/CreditCardValidatorTest.java | 0 docs/doxygen-user/central_repo.dox | 0 .../images/central_repo_content_viewer.png | Bin .../images/central_repo_interesting_items.png | Bin .../images/central_repo_manage_tags.png | Bin docs/doxygen-user/images/central_repo_options.png | Bin docs/doxygen-user/images/central_repo_postgres.png | Bin docs/doxygen-user/images/central_repo_sqlite.png | Bin docs/doxygen-user/images/central_repo_tag_file.png | Bin docs/doxygen-user/images/central_repo_types.png | Bin docs/doxygen-user/images/email_datasource_tree.png | Bin .../images/messages_datasource_tree.png | Bin ruleset.xml | 0 17 files changed, 2 insertions(+), 8 deletions(-) mode change 100755 => 100644 ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryWsmode.xml mode change 100755 => 100644 ImageGallery/src/org/sleuthkit/autopsy/imagegallery/layer.xml mode change 100755 => 100644 KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/CreditCardValidator.java mode change 100755 => 100644 KeywordSearch/test/unit/src/org/sleuthkit/autopsy/keywordsearch/CreditCardValidatorTest.java mode change 100755 => 100644 docs/doxygen-user/central_repo.dox mode change 100755 => 100644 docs/doxygen-user/images/central_repo_content_viewer.png mode change 100755 => 100644 docs/doxygen-user/images/central_repo_interesting_items.png mode change 100755 => 100644 docs/doxygen-user/images/central_repo_manage_tags.png mode change 100755 => 100644 docs/doxygen-user/images/central_repo_options.png mode change 100755 => 100644 docs/doxygen-user/images/central_repo_postgres.png mode change 100755 => 100644 docs/doxygen-user/images/central_repo_sqlite.png mode change 100755 => 100644 docs/doxygen-user/images/central_repo_tag_file.png mode change 100755 => 100644 docs/doxygen-user/images/central_repo_types.png mode change 100755 => 100644 docs/doxygen-user/images/email_datasource_tree.png mode change 100755 => 100644 docs/doxygen-user/images/messages_datasource_tree.png mode change 100755 => 100644 ruleset.xml diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java index d6ec19d48b..37c635b9f0 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java @@ -45,7 +45,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; @@ -344,13 +344,7 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang * @return The metrics snapshot. */ public MetricsSnapshot getMetricsSnapshot() { - MetricsSnapshot metricsSnapshot; - - synchronized (jobsLock) { - metricsSnapshot = queryCoordinationServiceForMetrics(); - } - - return metricsSnapshot; + return queryCoordinationServiceForMetrics(); } /** diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryWsmode.xml b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryWsmode.xml old mode 100755 new mode 100644 diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/layer.xml b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/layer.xml old mode 100755 new mode 100644 diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/CreditCardValidator.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/CreditCardValidator.java old mode 100755 new mode 100644 diff --git a/KeywordSearch/test/unit/src/org/sleuthkit/autopsy/keywordsearch/CreditCardValidatorTest.java b/KeywordSearch/test/unit/src/org/sleuthkit/autopsy/keywordsearch/CreditCardValidatorTest.java old mode 100755 new mode 100644 diff --git a/docs/doxygen-user/central_repo.dox b/docs/doxygen-user/central_repo.dox old mode 100755 new mode 100644 diff --git a/docs/doxygen-user/images/central_repo_content_viewer.png b/docs/doxygen-user/images/central_repo_content_viewer.png old mode 100755 new mode 100644 diff --git a/docs/doxygen-user/images/central_repo_interesting_items.png b/docs/doxygen-user/images/central_repo_interesting_items.png old mode 100755 new mode 100644 diff --git a/docs/doxygen-user/images/central_repo_manage_tags.png b/docs/doxygen-user/images/central_repo_manage_tags.png old mode 100755 new mode 100644 diff --git a/docs/doxygen-user/images/central_repo_options.png b/docs/doxygen-user/images/central_repo_options.png old mode 100755 new mode 100644 diff --git a/docs/doxygen-user/images/central_repo_postgres.png b/docs/doxygen-user/images/central_repo_postgres.png old mode 100755 new mode 100644 diff --git a/docs/doxygen-user/images/central_repo_sqlite.png b/docs/doxygen-user/images/central_repo_sqlite.png old mode 100755 new mode 100644 diff --git a/docs/doxygen-user/images/central_repo_tag_file.png b/docs/doxygen-user/images/central_repo_tag_file.png old mode 100755 new mode 100644 diff --git a/docs/doxygen-user/images/central_repo_types.png b/docs/doxygen-user/images/central_repo_types.png old mode 100755 new mode 100644 diff --git a/docs/doxygen-user/images/email_datasource_tree.png b/docs/doxygen-user/images/email_datasource_tree.png old mode 100755 new mode 100644 diff --git a/docs/doxygen-user/images/messages_datasource_tree.png b/docs/doxygen-user/images/messages_datasource_tree.png old mode 100755 new mode 100644 diff --git a/ruleset.xml b/ruleset.xml old mode 100755 new mode 100644 From c95fa28c4942da407a0596310df80a6c929eab5c Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Mon, 6 Nov 2017 13:03:28 -0500 Subject: [PATCH 47/69] Tracking auto ingest alerts via case nodes. --- .../autoingest/AutoIngestAlertFile.java | 108 ---------- .../autoingest/AutoIngestManager.java | 202 ++++++++++-------- 2 files changed, 111 insertions(+), 199 deletions(-) delete mode 100755 Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAlertFile.java diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAlertFile.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAlertFile.java deleted file mode 100755 index 40fff351eb..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAlertFile.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2015 Basis Technology Corp. - * Contact: carrier sleuthkit 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() { - } - -} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index b621cb514f..a0168cd9ee 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -64,6 +64,7 @@ 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.casemodule.CaseNodeData; import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.Lock; @@ -78,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; @@ -98,6 +98,7 @@ import org.sleuthkit.autopsy.ingest.IngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestJobStartResult; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestModuleError; +import org.sleuthkit.datamodel.Content; /** * An auto ingest manager is responsible for processing auto ingest jobs defined @@ -554,7 +555,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang ++maxPriority; for (AutoIngestJob job : prioritizedJobs) { try { - this.updateCoordinationServiceNode(job); + this.updateCoordinationServiceManifestNode(job); job.setPriority(maxPriority); } catch (CoordinationServiceException | InterruptedException ex) { throw new AutoIngestManagerException("Error updating case priority", ex); @@ -602,13 +603,13 @@ 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; try { - this.updateCoordinationServiceNode(prioritizedJob); + this.updateCoordinationServiceManifestNode(prioritizedJob); } catch (CoordinationServiceException | InterruptedException ex) { throw new AutoIngestManagerException("Error updating job priority", ex); } @@ -649,7 +650,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 +662,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 +756,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,20 +866,31 @@ 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 coordination service case node. + * + * @param caseNodeData The case node data. + * @param caseDirectoryPath The case directory. + */ + void updateCoordinationServiceCaseNode(CaseNodeData caseNodeData, Path caseDirectoryPath) throws CoordinationServiceException, InterruptedException { + 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 @@ -1147,8 +1159,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 +1173,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 +1198,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 +1214,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) { @@ -1219,14 +1231,14 @@ public final class AutoIngestManager extends Observable implements PropertyChang * status was not updated. * * @param manifest The manifest for upgrading the node. - * @param nodeData The node data. + * @param jobNodeData The auto ingest job node data. * * @throws InterruptedException if the thread running the input * directory scan task is interrupted while * blocked, i.e., if auto ingest is * shutting down. */ - 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 @@ -1240,7 +1252,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang /* * Create the recovery job. */ - AutoIngestJob job = new AutoIngestJob(nodeData); + AutoIngestJob job = new AutoIngestJob(jobNodeData); int numberOfCrashes = job.getNumberOfCrashes(); ++numberOfCrashes; job.setNumberOfCrashes(numberOfCrashes); @@ -1254,15 +1266,16 @@ public final class AutoIngestManager extends Observable implements PropertyChang } /* - * Update the coordination service node for the job. If - * this fails, leave the recovery to another host. + * Update the coordination service manifest node for + * the job. If this fails, leave the recovery to + * another host. */ try { - updateCoordinationServiceNode(job); + updateCoordinationServiceManifestNode(job); if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) { newPendingJobsList.add(job); } else { - newCompletedJobsList.add(new AutoIngestJob(nodeData)); + newCompletedJobsList.add(new AutoIngestJob(jobNodeData)); } } catch (CoordinationServiceException ex) { SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifestPath), ex); @@ -1270,13 +1283,15 @@ public final class AutoIngestManager extends Observable implements PropertyChang } /* - * Write the alert file and do the logging. + * Update the case node data 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); + CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); + caseNodeData.setErrorsOccurred(true); + updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); + } catch (CaseNodeData.InvalidDataException ex) { + SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to get case node data for %s", caseDirectoryPath), ex); } } if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) { @@ -1292,7 +1307,7 @@ 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(), jobNodeData.getCaseDirectoryPath()).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); } @@ -1352,15 +1367,16 @@ 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 +1523,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 +1705,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 +1721,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 +1901,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 +1917,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 +1947,16 @@ 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 + CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); + caseNodeData.setErrorsOccurred(true); + updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, currentJob.getManifest().getDataSourceFileName(), caseDirectoryPath); jobLogger.logJobCancelled(); } @@ -1994,7 +2004,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; @@ -2159,8 +2169,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. @@ -2169,7 +2177,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; @@ -2197,8 +2205,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. @@ -2207,7 +2213,7 @@ 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; } @@ -2255,8 +2261,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. @@ -2265,7 +2269,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 DataSource 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); @@ -2277,22 +2281,22 @@ 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 + CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); + caseNodeData.setErrorsOccurred(true); + updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); jobLogger.logMissingDataSource(); return null; } String deviceId = manifest.getDeviceId(); return new DataSource(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. @@ -2301,7 +2305,7 @@ 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, DataSource 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); @@ -2327,7 +2331,9 @@ public final class AutoIngestManager extends Observable implements PropertyChang // did we find a data source processor that can process the data source if (validDataSourceProcessorsMap.isEmpty()) { // This should never happen. We should add all unsupported data sources as logical files. - AutoIngestAlertFile.create(caseDirectoryPath); + CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); + caseNodeData.setErrorsOccurred(true); + updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); currentJob.setErrorsOccurred(true); jobLogger.logFailedToIdentifyDataSource(); SYS_LOGGER.log(Level.WARNING, "Unsupported data source {0} for {1}", new Object[]{dataSource.getPath(), manifestPath}); // NON-NLS @@ -2353,7 +2359,9 @@ 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); + CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); + caseNodeData.setErrorsOccurred(true); + updateCoordinationServiceCaseNode(caseNodeData, 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()}); @@ -2377,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. @@ -2387,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(DataSource dataSource) throws AutoIngestJobLoggerException, InterruptedException, CaseNodeData.InvalidDataException, CoordinationServiceException { Manifest manifest = currentJob.getManifest(); Path manifestPath = manifest.getFilePath(); Path caseDirectoryPath = currentJob.getCaseDirectoryPath(); @@ -2399,7 +2405,9 @@ 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 + CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); + caseNodeData.setErrorsOccurred(true); + updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); jobLogger.logNoDataSourceContent(); } break; @@ -2411,7 +2419,9 @@ 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 + CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); + caseNodeData.setErrorsOccurred(true); + updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); jobLogger.logNoDataSourceContent(); } break; @@ -2421,7 +2431,9 @@ 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 + CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); + caseNodeData.setErrorsOccurred(true); + updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); jobLogger.logFailedToAddDataSource(); break; } @@ -2435,7 +2447,9 @@ 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 + CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); + caseNodeData.setErrorsOccurred(true); + updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); jobLogger.logDataSourceProcessorCancelled(); } } @@ -2449,8 +2463,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. @@ -2459,7 +2471,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(DataSource 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); @@ -2491,7 +2503,9 @@ 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 + CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); + caseNodeData.setErrorsOccurred(true); + updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); for (String module : snapshot.getCancelledDataSourceIngestModules()) { SYS_LOGGER.log(Level.WARNING, String.format("%s ingest module cancelled for %s", module, manifestPath)); jobLogger.logIngestModuleCancelled(module); @@ -2501,7 +2515,9 @@ 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 + CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); + caseNodeData.setErrorsOccurred(true); + updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); jobLogger.logAnalysisCancelled(); CancellationReason cancellationReason = snapshot.getCancellationReason(); if (CancellationReason.NOT_CANCELLED != cancellationReason && CancellationReason.USER_CANCELLED != cancellationReason) { @@ -2514,13 +2530,17 @@ 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 + CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); + caseNodeData.setErrorsOccurred(true); + updateCoordinationServiceCaseNode(caseNodeData, 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 + CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); + caseNodeData.setErrorsOccurred(true); + updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); jobLogger.logAnalysisStartupError(); throw new AnalysisStartupException("Ingest manager error starting job", ingestJobStartResult.getStartupException()); } @@ -2529,7 +2549,9 @@ 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 + CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); + caseNodeData.setErrorsOccurred(true); + updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); jobLogger.logIngestJobSettingsErrors(); throw new AnalysisStartupException("Error(s) in ingest job settings"); } @@ -2548,8 +2570,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. @@ -2558,7 +2578,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(DataSource 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); @@ -2574,11 +2594,13 @@ 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 + CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); + caseNodeData.setErrorsOccurred(true); + updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); jobLogger.logFileExportError(); } } - + /** * A data source processor progress monitor does nothing. There is * currently no mechanism for showing or recording data source processor @@ -2740,7 +2762,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)); } @@ -2843,7 +2865,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"); @@ -2918,7 +2939,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang PARTIALLY_DELETED, FULLY_DELETED } - static final class AutoIngestManagerException extends Exception { private static final long serialVersionUID = 1L; From a17f2126675a3b815258e6c4ae0e8f1f5a9aca0d Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Mon, 6 Nov 2017 13:10:02 -0500 Subject: [PATCH 48/69] Cleanup. --- .../autopsy/casemodule/CaseNodeData.java | 141 ++++++++++++++++++ .../autoingest/AutoIngestManager.java | 3 +- 2 files changed, 142 insertions(+), 2 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/casemodule/CaseNodeData.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseNodeData.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseNodeData.java new file mode 100755 index 0000000000..a97f48c10d --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseNodeData.java @@ -0,0 +1,141 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2017 Basis Technology Corp. + * Contact: carrier sleuthkit 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.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 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); + } + } +} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index a0168cd9ee..2ce6e2cba8 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -98,7 +98,6 @@ import org.sleuthkit.autopsy.ingest.IngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestJobStartResult; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestModuleError; -import org.sleuthkit.datamodel.Content; /** * An auto ingest manager is responsible for processing auto ingest jobs defined @@ -114,7 +113,7 @@ import org.sleuthkit.datamodel.Content; * 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"; From ab77d2c5aadbad4e43171a3ac709bc8dafa1871f Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Mon, 6 Nov 2017 13:11:34 -0500 Subject: [PATCH 49/69] Cleanup. --- Core/src/org/sleuthkit/autopsy/casemodule/CaseNodeData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseNodeData.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseNodeData.java index a97f48c10d..1eceb084e6 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseNodeData.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseNodeData.java @@ -25,7 +25,7 @@ import java.nio.ByteBuffer; * An object that converts case data for a case directory coordination service * node to and from byte arrays. */ -public class CaseNodeData { +public final class CaseNodeData { private static final int CURRENT_VERSION = 0; From a8648cdbb14527ffaed14dde5da34d6bc5aa811c Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Tue, 7 Nov 2017 13:45:21 -0500 Subject: [PATCH 50/69] 3180: Move unit test to qa-functional test and adding Case creation and deletion --- Core/nbproject/project.xml | 40 ++++++++++ .../autopsy/ingest/IngestFileFiltersTest.java | 73 +++++++++++++++++++ .../testutils/FunctionalTestDspCallback.java} | 4 +- .../FunctionalTestDspProgressMonitor.java} | 2 +- .../autopsy/ingest/IngestFileFiltersTest.java | 53 -------------- 5 files changed, 116 insertions(+), 56 deletions(-) create mode 100755 Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java rename Core/test/{unit/src/org/sleuthkit/autopsy/testutils/UnitTestDspCallback.java => qa-functional/src/org/sleuthkit/autopsy/testutils/FunctionalTestDspCallback.java} (97%) rename Core/test/{unit/src/org/sleuthkit/autopsy/testutils/UnitTestDspProgressMonitor.java => qa-functional/src/org/sleuthkit/autopsy/testutils/FunctionalTestDspProgressMonitor.java} (95%) delete mode 100755 Core/test/unit/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml index 25e17dd3eb..07b6d666f8 100755 --- a/Core/nbproject/project.xml +++ b/Core/nbproject/project.xml @@ -244,6 +244,46 @@ org.netbeans.libs.junit4 + + org.netbeans.modules.jellytools.java + + + + org.netbeans.modules.jellytools.platform + + + + org.netbeans.modules.jemmy + + + + org.netbeans.modules.nbjunit + + + + + qa-functional + + org.netbeans.libs.junit4 + + + + org.netbeans.modules.jellytools.java + + + + org.netbeans.modules.jellytools.platform + + + + org.netbeans.modules.jemmy + + + + org.netbeans.modules.nbjunit + + + diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java new file mode 100755 index 0000000000..bc74a6f653 --- /dev/null +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java @@ -0,0 +1,73 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2017 Basis Technology Corp. + * Contact: carrier sleuthkit 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 static junit.framework.Assert.assertTrue; + +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"); + } +} diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/testutils/UnitTestDspCallback.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/FunctionalTestDspCallback.java similarity index 97% rename from Core/test/unit/src/org/sleuthkit/autopsy/testutils/UnitTestDspCallback.java rename to Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/FunctionalTestDspCallback.java index c6adb1f24c..cfa9f3dc59 100755 --- a/Core/test/unit/src/org/sleuthkit/autopsy/testutils/UnitTestDspCallback.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/FunctionalTestDspCallback.java @@ -31,7 +31,7 @@ import org.sleuthkit.datamodel.Content; * thread. */ @Immutable -public class UnitTestDspCallback extends DataSourceProcessorCallback { +public class FunctionalTestDspCallback extends DataSourceProcessorCallback { private final Object monitor; private final List errorMessages = new ArrayList<>(); @@ -46,7 +46,7 @@ public class UnitTestDspCallback extends DataSourceProcessorCallback { * @param monitor A monitor for the callback to signal when the data source * processor completes its processing. */ - UnitTestDspCallback(Object monitor) { + FunctionalTestDspCallback(Object monitor) { this.monitor = monitor; } diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/testutils/UnitTestDspProgressMonitor.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/FunctionalTestDspProgressMonitor.java similarity index 95% rename from Core/test/unit/src/org/sleuthkit/autopsy/testutils/UnitTestDspProgressMonitor.java rename to Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/FunctionalTestDspProgressMonitor.java index 1f856e6500..03d26eb9b2 100755 --- a/Core/test/unit/src/org/sleuthkit/autopsy/testutils/UnitTestDspProgressMonitor.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/FunctionalTestDspProgressMonitor.java @@ -25,7 +25,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgress * A data source processor progress monitor for unit testing. */ @Immutable -public class UnitTestDspProgressMonitor implements DataSourceProcessorProgressMonitor { +public class FunctionalTestDspProgressMonitor implements DataSourceProcessorProgressMonitor { /** * Switches the progress indicator to indeterminate mode (the total number diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java deleted file mode 100755 index 4dbec8bdc8..0000000000 --- a/Core/test/unit/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011-2017 Basis Technology Corp. - * Contact: carrier sleuthkit 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 org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.openide.modules.Places; - -public class IngestFileFiltersTest { - - public IngestFileFiltersTest() { - } - - @BeforeClass - public static void setUpClass() { - } - - @AfterClass - public static void tearDownClass() { - } - - @Before - public void setUp() { - } - - @After - public void tearDown() { - } - - @Test - public void testFilters() { - Places.getUserDirectory().getAbsoluteFile(); - System.out.println("Test filter"); - } -} From 82ec21ac1a6b2eb2b282a7143d7579eefa88c82e Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Tue, 7 Nov 2017 13:49:19 -0500 Subject: [PATCH 51/69] 3180: delete unused import --- .../src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java index bc74a6f653..843e9e53fa 100755 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java @@ -18,8 +18,6 @@ */ package org.sleuthkit.autopsy.ingest; -import static junit.framework.Assert.assertTrue; - import java.io.File; import java.io.IOException; import java.nio.file.Path; From 635537496ae886795e1d1197c83567ff37395100 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 7 Nov 2017 13:54:35 -0500 Subject: [PATCH 52/69] fixed height of External Viewer Global Settings Panel --- .../ExternalViewerGlobalSettingsPanel.form | 83 +++++++++++++------ .../ExternalViewerGlobalSettingsPanel.java | 59 +++++++------ 2 files changed, 94 insertions(+), 48 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form index e00c4a966f..50706d661f 100755 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form @@ -3,7 +3,7 @@
- + @@ -32,19 +32,24 @@ + + + + + - + - + @@ -55,7 +60,7 @@ - + @@ -81,13 +86,18 @@ - + + + + + + @@ -103,7 +113,7 @@ - + @@ -114,7 +124,7 @@ - + @@ -137,6 +147,11 @@ + + + + + @@ -149,42 +164,35 @@ - - - - - - - - - - - + + + + - + - + - - - + + + - + @@ -224,6 +232,15 @@ + + + + + + + + + @@ -237,6 +254,15 @@ + + + + + + + + + @@ -250,6 +276,15 @@ + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java index b2497baed8..f87c6b4e33 100755 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java @@ -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) From b85a41b4b9f5ade8e5a6cdde7bada63d53cacf06 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 7 Nov 2017 13:54:58 -0500 Subject: [PATCH 53/69] fixed height of File ext mismatch settings Panel --- .../FileExtMismatchSettingsPanel.form | 87 +++++++++++++------ .../FileExtMismatchSettingsPanel.java | 62 ++++++++----- 2 files changed, 101 insertions(+), 48 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.form index 162aef8994..f8ffc03428 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.form @@ -1,6 +1,11 @@ + + + + + @@ -16,12 +21,12 @@ - + - + @@ -29,7 +34,7 @@ - + @@ -37,36 +42,45 @@ - - - + + + - + - + + + + - + + + + + + + @@ -76,23 +90,26 @@ - + - + + + + + - + - + - + - @@ -101,14 +118,14 @@ - - - + + + - + - + @@ -142,6 +159,15 @@ + + + + + + + + + @@ -166,6 +192,11 @@ + + + + + @@ -198,16 +229,16 @@ - + - - - + + + - + @@ -221,6 +252,12 @@ + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.java index 1d5470b4df..85cf916f2c 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.java @@ -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) ); }// //GEN-END:initComponents From 88d668ffeb7c7f4039d5156350601d21424298fa Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 8 Nov 2017 00:54:53 -0500 Subject: [PATCH 54/69] Wait cursor set for 'Ingest Module Settings' button. --- .../experimental/configuration/AutoIngestSettingsPanel.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.java index 0d449fdb02..58f68f3b54 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AutoIngestSettingsPanel.java @@ -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; @@ -513,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); @@ -526,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) { From 35ce34137239fff2c8eb97719b44c3e88f8c2208 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Wed, 8 Nov 2017 17:41:10 -0500 Subject: [PATCH 55/69] Workaround for JComponent.addPropertyChangeListener calls in ctor --- .../autopsy/ingest/IngestOptionsPanel.java | 32 +++++++++++++++++-- .../autopsy/ingest/ProfilePanel.java | 24 +++++++++++++- .../GlobalListSettingsPanel.java | 27 ++++++++++++++-- .../KeywordSearchGlobalSettingsPanel.java | 31 ++++++++++++++++-- 4 files changed, 105 insertions(+), 9 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestOptionsPanel.java index 1c761e8578..edd98b5034 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestOptionsPanel.java @@ -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.(JPanel.java:86) at + * javax.swing.JPanel.(JPanel.java:109) at + * javax.swing.JPanel.(JPanel.java:117) + * + * When this happens, the following child components of this panel 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 diff --git a/Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java b/Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java index 3110947488..250435ae38 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java @@ -174,7 +174,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.(JPanel.java:86) at + * javax.swing.JPanel.(JPanel.java:109) at + * javax.swing.JPanel.(JPanel.java:117) + * + * When this happens, the following child components of this panel 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; diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java index e28cd75654..f5294db294 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java @@ -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.(JPanel.java:86) at + * javax.swing.JPanel.(JPanel.java:109) at + * javax.swing.JPanel.(JPanel.java:117) + * + * When this happens, the following child components of this panel 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 diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java index 8e820b4c74..bd2dc11a43 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java @@ -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.(JPanel.java:86) at + * javax.swing.JPanel.(JPanel.java:109) at + * javax.swing.JPanel.(JPanel.java:117) + * + * When this happens, the following child components of this panel 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 From b4d2cbd447de2759c94d588dee40b012827ec62f Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Wed, 8 Nov 2017 17:45:39 -0500 Subject: [PATCH 56/69] Update comment in some JPanel subclasses --- .../org/sleuthkit/autopsy/ingest/IngestOptionsPanel.java | 6 +++--- Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java | 6 +++--- .../autopsy/keywordsearch/GlobalListSettingsPanel.java | 6 +++--- .../keywordsearch/KeywordSearchGlobalSettingsPanel.java | 6 +++--- .../core.jar/org/netbeans/core/startup/Bundle.properties | 4 ++-- .../org/netbeans/core/windows/view/ui/Bundle.properties | 6 +++--- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestOptionsPanel.java index edd98b5034..40f3d1c298 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestOptionsPanel.java @@ -156,9 +156,9 @@ public class IngestOptionsPanel extends IngestModuleGlobalSettingsPanel implemen * javax.swing.JPanel.(JPanel.java:109) at * javax.swing.JPanel.(JPanel.java:117) * - * When this happens, the following child components of this panel have - * not been constructed yet, since this panel's constructor has not been - * called yet. + * 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); diff --git a/Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java b/Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java index 250435ae38..75588d5ab1 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java @@ -190,9 +190,9 @@ class ProfilePanel extends IngestModuleGlobalSettingsPanel { * javax.swing.JPanel.(JPanel.java:109) at * javax.swing.JPanel.(JPanel.java:117) * - * When this happens, the following child components of this panel have - * not been constructed yet, since this panel's constructor has not been - * called yet. + * 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); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java index f5294db294..862635ad4a 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java @@ -154,9 +154,9 @@ final class GlobalListSettingsPanel extends javax.swing.JPanel implements Option * javax.swing.JPanel.(JPanel.java:109) at * javax.swing.JPanel.(JPanel.java:117) * - * When this happens, the following child components of this panel have - * not been constructed yet, since this panel's constructor has not been - * called yet. + * 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); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java index bd2dc11a43..c34e672a1c 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java @@ -67,9 +67,9 @@ final class KeywordSearchGlobalSettingsPanel extends IngestModuleGlobalSettingsP * javax.swing.JPanel.(JPanel.java:109) at * javax.swing.JPanel.(JPanel.java:117) * - * When this happens, the following child components of this panel have - * not been constructed yet, since this panel's constructor has not been - * called yet. + * 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); diff --git a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties index 2922cd2054..0de39782ca 100644 --- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Thu, 07 Sep 2017 13:53:53 -0400 +#Wed, 08 Nov 2017 17:45:11 -0500 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=314 SPLASH_WIDTH=538 @@ -8,4 +8,4 @@ SplashRunningTextBounds=0,289,538,18 SplashRunningTextColor=0x0 SplashRunningTextFontSize=19 -currentVersion=Autopsy 4.4.2 +currentVersion=Autopsy 4.5.0 diff --git a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties index 2ac51b0cbd..fa55dddb62 100644 --- a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties +++ b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -1,4 +1,4 @@ #Updated by build script -#Thu, 07 Sep 2017 13:53:53 -0400 -CTL_MainWindow_Title=Autopsy 4.4.2 -CTL_MainWindow_Title_No_Project=Autopsy 4.4.2 +#Wed, 08 Nov 2017 17:45:11 -0500 +CTL_MainWindow_Title=Autopsy 4.5.0 +CTL_MainWindow_Title_No_Project=Autopsy 4.5.0 From ca64d9a3977450207a1c17bea13ded8599c902b0 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 10 Nov 2017 10:28:47 -0500 Subject: [PATCH 57/69] Pulling node data to determine case status. --- .../casemodule/MultiUserCaseManager.java | 142 ++++++++++++------ .../CaseNodeData.java | 2 +- .../autoingest/AutoIngestManager.java | 117 ++++++--------- 3 files changed, 145 insertions(+), 116 deletions(-) rename Core/src/org/sleuthkit/autopsy/{casemodule => coordinationservice}/CaseNodeData.java (98%) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java index d0baf94bc9..bedc09d799 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java @@ -30,6 +30,7 @@ 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; @@ -40,7 +41,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; final class MultiUserCaseManager { private static final Logger LOGGER = Logger.getLogger(MultiUserCaseManager.class.getName()); - private static final String LOG_FILE_NAME = "auto_ingest_log.txt"; + private static final String ALERT_FILE_NAME = "autoingest.alert"; private static MultiUserCaseManager instance; private CoordinationService coordinationService; @@ -82,19 +83,74 @@ final class MultiUserCaseManager { List cases = new ArrayList<>(); List nodeList = coordinationService.getNodeList(CoordinationService.CategoryNode.CASES); for (String node : nodeList) { - Path casePath = Paths.get(node); - File caseFolder = casePath.toFile(); - if(caseFolder.exists()) { - File[] autFiles = caseFolder.listFiles((dir, name) -> name.toLowerCase().endsWith(".aut")); - if(autFiles != null && autFiles.length > 0) { - try { - CaseMetadata caseMetadata = new CaseMetadata(Paths.get(autFiles[0].getAbsolutePath())); - cases.add(new MultiUserCase(casePath, caseMetadata)); - } catch (CaseMetadata.CaseMetadataException | MultiUserCase.MultiUserCaseException ex) { - LOGGER.log(Level.SEVERE, String.format("Error reading case metadata file '%s'.", autFiles[0].getAbsolutePath()), ex); + 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; } @@ -112,7 +168,7 @@ final class MultiUserCaseManager { */ Case.openAsCurrentCase(caseMetadataFilePath.toString()); } - + /** * Exception type thrown when there is an error completing a multi-user case * manager operation. @@ -143,7 +199,7 @@ final class MultiUserCaseManager { } } - + /** * A representation of a multi-user case. */ @@ -154,21 +210,22 @@ final class MultiUserCaseManager { 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. + * @param caseMetadata The case metadata. + * + * @throws MultiUserCaseException If no case metadata (.aut) file is + * found in the case directory. */ - MultiUserCase(Path caseDirectoryPath, CaseMetadata caseMetadata) throws MultiUserCaseException { + 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); @@ -194,8 +251,8 @@ final class MultiUserCaseManager { } /** - * 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. + * 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. */ @@ -204,8 +261,8 @@ final class MultiUserCaseManager { } /** - * Gets the creation date for the case, defined as the create time of the - * case metadata file. + * Gets the creation date for the case, defined as the create time of + * the case metadata file. * * @return The case creation date. */ @@ -214,8 +271,8 @@ final class MultiUserCaseManager { } /** - * Gets the last accessed date for the case, defined as the last accessed - * time of the case metadata file. + * Gets the last accessed date for the case, defined as the last + * accessed time of the case metadata file. * * @return The last accessed date. */ @@ -225,7 +282,7 @@ final class MultiUserCaseManager { /** * Gets metadata (.aut) file name. - * + * * @return The metadata file name. */ String getMetadataFileName() { @@ -233,17 +290,12 @@ final class MultiUserCaseManager { } /** - * Gets the status of this case based on the auto ingest result file in the - * case directory. + * Gets the status of this case. * * @return See CaseStatus enum definition. */ CaseStatus getStatus() { - if(caseDirectoryPath.resolve("autoingest.alert").toFile().exists()) { - return CaseStatus.ALERT; - } else { - return CaseStatus.OK; - } + return status; } /** @@ -252,7 +304,7 @@ final class MultiUserCaseManager { * @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) @@ -276,7 +328,7 @@ final class MultiUserCaseManager { } } - if(autFile == null || !autFile.isFile()) { + if (autFile == null || !autFile.isFile()) { throw new MultiUserCaseException(String.format("No case metadata (.aut) file found in the case directory '%s'.", caseDirectoryPath.toString())); } @@ -334,14 +386,15 @@ final class MultiUserCaseManager { static class LastAccessedDateDescendingComparator implements Comparator { /** - * Compares two MultiUserCase objects for order based on last accessed - * date (descending). + * 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. + * @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) { @@ -357,8 +410,8 @@ final class MultiUserCaseManager { private static final long serialVersionUID = 1L; /** - * Constructs an exception to throw when there is a problem creating a - * multi-user case. + * Constructs an exception to throw when there is a problem creating + * a multi-user case. * * @param message The exception message. */ @@ -367,11 +420,12 @@ final class MultiUserCaseManager { } /** - * Constructs an exception to throw when there is a problem creating a - * multi-user case. + * 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. + * @param cause The cause of the exception, if it was an + * exception. */ private MultiUserCaseException(String message, Throwable cause) { super(message, cause); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseNodeData.java b/Core/src/org/sleuthkit/autopsy/coordinationservice/CaseNodeData.java similarity index 98% rename from Core/src/org/sleuthkit/autopsy/casemodule/CaseNodeData.java rename to Core/src/org/sleuthkit/autopsy/coordinationservice/CaseNodeData.java index 1eceb084e6..0b220e04b2 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseNodeData.java +++ b/Core/src/org/sleuthkit/autopsy/coordinationservice/CaseNodeData.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.casemodule; +package org.sleuthkit.autopsy.coordinationservice; import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index 2ce6e2cba8..e6187877c3 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -64,7 +64,7 @@ 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.casemodule.CaseNodeData; +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; @@ -867,9 +867,9 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen /** * Sets the coordination service manifest node. * - * 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. + * 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. */ @@ -879,14 +879,19 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen byte[] rawData = nodeData.toArray(); coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath, rawData); } - + /** - * Sets the coordination service case node. + * Sets the error flag for case node data given a case directory path. * - * @param caseNodeData The case node data. - * @param caseDirectoryPath The case directory. + * @param caseDirectoryPath The case directory path. + * + * @throws CoordinationService.CoordinationServiceException + * @throws InterruptedException + * @throws CaseNodeData.InvalidDataException */ - void updateCoordinationServiceCaseNode(CaseNodeData caseNodeData, Path caseDirectoryPath) throws CoordinationServiceException, InterruptedException { + 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); } @@ -1052,8 +1057,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen 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(); @@ -1067,8 +1072,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen } /* - * 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()); @@ -1088,7 +1093,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen break; case DELETED: /* - * Ignore jobs marked as "deleted." + * Ignore jobs marked as "deleted." */ break; default: @@ -1198,8 +1203,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen private void addNewPendingJob(Manifest manifest) throws InterruptedException, AutoIngestJobException { /* * 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. + * 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 @@ -1229,7 +1234,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen * the node that was processing the job crashed and the processing * status was not updated. * - * @param manifest The manifest for upgrading the node. + * @param manifest The manifest for upgrading the node. * @param jobNodeData The auto ingest job node data. * * @throws InterruptedException if the thread running the input @@ -1265,9 +1270,9 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen } /* - * Update the coordination service manifest node for - * the job. If this fails, leave the recovery to - * another host. + * Update the coordination service manifest node for the + * job. If this fails, leave the recovery to another + * host. */ try { updateCoordinationServiceManifestNode(job); @@ -1286,9 +1291,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen */ if (null != caseDirectoryPath) { try { - CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); - caseNodeData.setErrorsOccurred(true); - updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); + setCaseNodeDataErrorsOccurred(caseDirectoryPath); } catch (CaseNodeData.InvalidDataException ex) { SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to get case node data for %s", caseDirectoryPath), ex); } @@ -1367,11 +1370,10 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen /* * 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. + * 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) { @@ -1953,9 +1955,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen if (currentJob.isCanceled()) { Path caseDirectoryPath = currentJob.getCaseDirectoryPath(); if (null != caseDirectoryPath) { - CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); - caseNodeData.setErrorsOccurred(true); - updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); + setCaseNodeDataErrorsOccurred(caseDirectoryPath); AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, currentJob.getManifest().getDataSourceFileName(), caseDirectoryPath); jobLogger.logJobCancelled(); } @@ -2280,9 +2280,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen if (!dataSource.exists()) { SYS_LOGGER.log(Level.SEVERE, "Missing data source for {0}", manifestPath); currentJob.setErrorsOccurred(true); - CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); - caseNodeData.setErrorsOccurred(true); - updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); + setCaseNodeDataErrorsOccurred(caseDirectoryPath); jobLogger.logMissingDataSource(); return null; } @@ -2330,9 +2328,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen // did we find a data source processor that can process the data source if (validDataSourceProcessorsMap.isEmpty()) { // This should never happen. We should add all unsupported data sources as logical files. - CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); - caseNodeData.setErrorsOccurred(true); - updateCoordinationServiceCaseNode(caseNodeData, 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 @@ -2358,9 +2354,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen // 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. - CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); - caseNodeData.setErrorsOccurred(true); - updateCoordinationServiceCaseNode(caseNodeData, 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()}); @@ -2404,9 +2398,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen jobLogger.logDataSourceAdded(); if (dataSource.getContent().isEmpty()) { currentJob.setErrorsOccurred(true); - CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); - caseNodeData.setErrorsOccurred(true); - updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); + setCaseNodeDataErrorsOccurred(caseDirectoryPath); jobLogger.logNoDataSourceContent(); } break; @@ -2418,9 +2410,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen jobLogger.logDataSourceAdded(); if (dataSource.getContent().isEmpty()) { currentJob.setErrorsOccurred(true); - CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); - caseNodeData.setErrorsOccurred(true); - updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); + setCaseNodeDataErrorsOccurred(caseDirectoryPath); jobLogger.logNoDataSourceContent(); } break; @@ -2430,9 +2420,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen SYS_LOGGER.log(Level.SEVERE, "Critical error running data source processor for {0}: {1}", new Object[]{manifestPath, errorMessage}); } currentJob.setErrorsOccurred(true); - CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); - caseNodeData.setErrorsOccurred(true); - updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); + setCaseNodeDataErrorsOccurred(caseDirectoryPath); jobLogger.logFailedToAddDataSource(); break; } @@ -2446,9 +2434,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen */ SYS_LOGGER.log(Level.WARNING, "Cancellation while waiting for data source processor for {0}", manifestPath); currentJob.setErrorsOccurred(true); - CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); - caseNodeData.setErrorsOccurred(true); - updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); + setCaseNodeDataErrorsOccurred(caseDirectoryPath); jobLogger.logDataSourceProcessorCancelled(); } } @@ -2502,9 +2488,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen if (!cancelledModules.isEmpty()) { SYS_LOGGER.log(Level.WARNING, String.format("Ingest module(s) cancelled for %s", manifestPath)); currentJob.setErrorsOccurred(true); - CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); - caseNodeData.setErrorsOccurred(true); - updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); + 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); @@ -2514,9 +2498,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen } else { currentJob.setProcessingStage(AutoIngestJob.Stage.CANCELLING, Date.from(Instant.now())); currentJob.setErrorsOccurred(true); - CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); - caseNodeData.setErrorsOccurred(true); - updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); + setCaseNodeDataErrorsOccurred(caseDirectoryPath); jobLogger.logAnalysisCancelled(); CancellationReason cancellationReason = snapshot.getCancellationReason(); if (CancellationReason.NOT_CANCELLED != cancellationReason && CancellationReason.USER_CANCELLED != cancellationReason) { @@ -2529,17 +2511,13 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen SYS_LOGGER.log(Level.SEVERE, String.format("%s ingest module startup error for %s", error.getModuleDisplayName(), manifestPath), error.getThrowable()); } currentJob.setErrorsOccurred(true); - CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); - caseNodeData.setErrorsOccurred(true); - updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); + 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); - CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); - caseNodeData.setErrorsOccurred(true); - updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); + setCaseNodeDataErrorsOccurred(caseDirectoryPath); jobLogger.logAnalysisStartupError(); throw new AnalysisStartupException("Ingest manager error starting job", ingestJobStartResult.getStartupException()); } @@ -2548,9 +2526,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen SYS_LOGGER.log(Level.SEVERE, "Ingest job settings error for {0}: {1}", new Object[]{manifestPath, warning}); } currentJob.setErrorsOccurred(true); - CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); - caseNodeData.setErrorsOccurred(true); - updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); + setCaseNodeDataErrorsOccurred(caseDirectoryPath); jobLogger.logIngestJobSettingsErrors(); throw new AnalysisStartupException("Error(s) in ingest job settings"); } @@ -2593,9 +2569,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen } catch (FileExportException ex) { SYS_LOGGER.log(Level.SEVERE, String.format("Error doing file export for %s", manifestPath), ex); currentJob.setErrorsOccurred(true); - CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())); - caseNodeData.setErrorsOccurred(true); - updateCoordinationServiceCaseNode(caseNodeData, caseDirectoryPath); + setCaseNodeDataErrorsOccurred(caseDirectoryPath); jobLogger.logFileExportError(); } } @@ -2938,6 +2912,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen PARTIALLY_DELETED, FULLY_DELETED } + static final class AutoIngestManagerException extends Exception { private static final long serialVersionUID = 1L; @@ -2952,4 +2927,4 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen } -} \ No newline at end of file +} From 56c5cd92cb0484646e111f9c7d2f37954a6720ba Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Mon, 13 Nov 2017 08:47:01 -0500 Subject: [PATCH 58/69] Revert changes to the public api --- .../HashDbCreateDatabaseDialog.java | 2 +- .../HashDbImportDatabaseDialog.java | 2 +- .../modules/hashdatabase/HashDbManager.java | 62 ++++++------------- .../hashdatabase/HashLookupModuleFactory.java | 2 +- .../hashdatabase/HashLookupSettingsPanel.java | 18 +++--- .../configuration/SharedConfiguration.java | 4 +- 6 files changed, 31 insertions(+), 59 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java index ab3efb8afb..0bea515d14 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java @@ -338,7 +338,7 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { String errorMessage = NbBundle .getMessage(this.getClass(), "HashDbCreateDatabaseDialog.errMsg.hashDbCreationErr"); 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, diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java index 66037cccf9..012544bdab 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java @@ -514,7 +514,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, diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index ec28c31747..fb2edad967 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -147,7 +147,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); @@ -155,12 +154,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()) { @@ -175,7 +169,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 = addFileHashDatabase(SleuthkitJNI.openHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType); } catch (TskCoreException ex) { throw new HashDbManagerException(ex.getMessage()); } @@ -200,7 +194,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 { @@ -212,14 +205,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); @@ -239,14 +226,14 @@ 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 = addFileHashDatabase(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 HashDb addFileHashDatabase(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); @@ -281,7 +268,7 @@ public class HashDbManager implements PropertyChangeListener { return hashDb; } - public CentralRepoHashDb addExistingCentralRepoHashSet(String hashSetName, String version, int referenceSetID, + CentralRepoHashDb addExistingCentralRepoHashSet(String hashSetName, String version, int referenceSetID, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType, boolean readOnly) throws TskCoreException{ @@ -414,23 +401,22 @@ public class HashDbManager implements PropertyChangeListener { } /** - * Gets all of the hash databases used to classify files as known or known - * bad. + * Gets all of the HashDbs used to classify files as known or known + * bad. Will not return central repository databases. * * @return A list, possibly empty, of hash databases. */ - @Deprecated public synchronized List getAllHashSets() { - return getAllFileTypeHashSets(); + return getAllFileHashSets(); } /** - * Gets all of the file type hash databases used to classify files as known or known + * Gets all of the file hash databases used to classify files as known or known * bad. * * @return A list, possibly empty, of hash databases. */ - public synchronized List getAllFileTypeHashSets() { + synchronized List getAllFileHashSets() { List hashDbs = new ArrayList<>(); this.hashSets.stream().filter((thisSet) -> (thisSet instanceof HashDb)).forEach((thisSet) -> { hashDbs.add((HashDb)thisSet); @@ -440,28 +426,21 @@ public class HashDbManager implements PropertyChangeListener { /** * 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. */ - public synchronized List getAllHashDatabases(){ - List 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 refreshAndGetAllHashDatabases(){ + synchronized List getAllHashDatabases(){ 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 hashDbs = new ArrayList<>(); + hashDbs.addAll(this.hashSets); + return hashDbs; } /** @@ -469,7 +448,6 @@ public class HashDbManager implements PropertyChangeListener { * * @return A list, possibly empty, of hash databases. */ - @Deprecated public synchronized List getKnownFileHashSets() { List hashDbs = new ArrayList<>(); this.hashSets.stream().filter((thisSet) -> ((thisSet instanceof HashDb) && (thisSet.getKnownFilesType() == HashDb.KnownFilesType.KNOWN))).forEach((thisSet) -> { @@ -483,7 +461,7 @@ public class HashDbManager implements PropertyChangeListener { * * @return A list, possibly empty, of hash databases. */ - public synchronized List getKnownFileHashDatabases() { + synchronized List getKnownFileHashDatabases() { List hashDbs = new ArrayList<>(); this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == HashDb.KnownFilesType.KNOWN)).forEach((db) -> { hashDbs.add(db); @@ -496,7 +474,6 @@ public class HashDbManager implements PropertyChangeListener { * * @return A list, possibly empty, of hash databases. */ - @Deprecated public synchronized List getKnownBadFileHashSets() { List hashDbs = new ArrayList<>(); this.hashSets.stream().filter((thisSet) -> ((thisSet instanceof HashDb) && (thisSet.getKnownFilesType() == HashDb.KnownFilesType.KNOWN_BAD))).forEach((thisSet) -> { @@ -510,7 +487,7 @@ public class HashDbManager implements PropertyChangeListener { * * @return A list, possibly empty, of hash databases. */ - public synchronized List getNotableFileHashDatabases() { + synchronized List getNotableFileHashDatabases() { List hashDbs = new ArrayList<>(); this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == HashDb.KnownFilesType.KNOWN_BAD)).forEach((db) -> { hashDbs.add(db); @@ -523,7 +500,6 @@ public class HashDbManager implements PropertyChangeListener { * * @return A list, possibly empty, of hash databases. */ - @Deprecated public synchronized List getUpdateableHashSets() { List updateableDbs = new ArrayList<>(); List updateableHashSets = getUpdateableHashSets(this.hashSets); @@ -625,7 +601,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()); + addFileHashDatabase(SleuthkitJNI.openHashDatabase(dbPath), hashDbInfo.getHashSetName(), hashDbInfo.getSearchDuringIngest(), hashDbInfo.getSendIngestMessages(), hashDbInfo.getKnownFilesType()); } else { logger.log(Level.WARNING, Bundle.HashDbManager_noDbPath_message(hashDbInfo.getHashSetName())); allDatabasesLoadedCorrectly = false; diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleFactory.java index 19a1d5ee21..52ae48c8cd 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleFactory.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleFactory.java @@ -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().getAllHashDatabases()); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java index 27249e1e5a..46b636af82 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java @@ -27,7 +27,6 @@ import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import javax.swing.JComponent; -import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; @@ -306,16 +305,13 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan public void saveSettings() { //Checking for for any unindexed databases List unindexed = new ArrayList<>(); - for (HashDatabase hashSet : hashSetManager.getAllHashDatabases()) { - if(hashSet instanceof HashDb){ - HashDb db = (HashDb)hashSet; - try { - if (!db.hasIndex()) { - unindexed.add(db); - } - } catch (TskCoreException ex) { - Logger.getLogger(HashLookupSettingsPanel.class.getName()).log(Level.SEVERE, "Error getting index info for hash database", ex); //NON-NLS + for (HashDb db : hashSetManager.getAllFileHashSets()) { + try { + if (!db.hasIndex()) { + unindexed.add(db); } + } catch (TskCoreException ex) { + Logger.getLogger(HashLookupSettingsPanel.class.getName()).log(Level.SEVERE, "Error getting index info for hash database", ex); //NON-NLS } } @@ -550,7 +546,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan } void refreshModel() { - hashSets = HashDbManager.getInstance().refreshAndGetAllHashDatabases(); + hashSets = HashDbManager.getInstance().getAllHashDatabases(); refreshDisplay(); } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java index b715b7d309..ccb2e49e54 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java @@ -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 hashDbs = HashDbManager.getInstance().getAllFileTypeHashSets(); + List 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 (HashDb hashDb : hashDbManager.getAllHashSets()) { if (hashDb.hasIndexOnly()) { results.add(hashDb.getIndexPath()); } else { From 5c2b89995e74c9ee7f52135aca1ae61aa23a68aa Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Mon, 13 Nov 2017 13:56:40 -0500 Subject: [PATCH 59/69] Switched around names of HashDb and HashDatabase --- .../datamodel/EamGlobalSet.java | 6 +- .../AddContentToHashDbAction.java | 10 +- .../AddHashValuesToDatabaseDialog.java | 6 +- ...AddHashValuesToDatabaseProgressDialog.java | 6 +- .../HashDbCreateDatabaseDialog.java | 6 +- .../HashDbImportDatabaseDialog.java | 7 +- .../hashdatabase/HashDbIngestModule.java | 22 +- .../modules/hashdatabase/HashDbManager.java | 243 ++++++++---------- .../hashdatabase/HashLookupModuleFactory.java | 2 +- .../HashLookupModuleSettings.java | 16 +- .../HashLookupModuleSettingsPanel.java | 36 +-- .../hashdatabase/HashLookupSettings.java | 28 +- .../hashdatabase/HashLookupSettingsPanel.java | 58 ++--- .../ImportCentralRepoDbProgressDialog.java | 14 +- .../modules/hashdatabase/ModalNoButtons.java | 16 +- .../taggedhashes/AddTaggedHashesToHashDb.java | 4 +- .../AddTaggedHashesToHashDbConfigPanel.form | 2 +- .../AddTaggedHashesToHashDbConfigPanel.java | 14 +- .../configuration/SharedConfiguration.java | 30 ++- 19 files changed, 246 insertions(+), 280 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalSet.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalSet.java index e4292dc6ca..80e7d9cb8b 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalSet.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalSet.java @@ -150,11 +150,11 @@ public class EamGlobalSet { * Return the FileKnown status as a KnownFilesType * @return KNOWN or KNOWN_BAD */ - public HashDbManager.HashDb.KnownFilesType getKnownStatus(){ + public HashDbManager.HashDatabase.KnownFilesType getKnownStatus(){ if(fileKnownStatus.equals(TskData.FileKnown.BAD)){ - return HashDbManager.HashDb.KnownFilesType.KNOWN_BAD; + return HashDbManager.HashDatabase.KnownFilesType.KNOWN_BAD; } - return HashDbManager.HashDb.KnownFilesType.KNOWN; + return HashDbManager.HashDatabase.KnownFilesType.KNOWN; } /** diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddContentToHashDbAction.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddContentToHashDbAction.java index 6c58402fd6..effa123af9 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddContentToHashDbAction.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddContentToHashDbAction.java @@ -35,7 +35,7 @@ import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.HashUtility; import org.sleuthkit.datamodel.TskCoreException; -import static org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase; +import static org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; /** * Instances of this Action allow users to content to a hash database. @@ -106,9 +106,9 @@ 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 hashDatabases = HashDbManager.getInstance().getUpdateableHashDatabases(); + final List hashDatabases = HashDbManager.getInstance().getUpdateableHashSets(); if (!hashDatabases.isEmpty()) { - for (final HashDatabase database : hashDatabases) { + for (final HashDb database : hashDatabases) { JMenuItem databaseItem = add(database.getHashSetName()); databaseItem.addActionListener(new ActionListener() { @Override @@ -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 files, HashDatabase hashSet) { + private void addFilesToHashSet(final Collection files, HashDb hashSet) { for (AbstractFile file : files) { String md5Hash = file.getMd5Hash(); if (null != md5Hash) { diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseDialog.java index debe46f47c..1fe05701ce 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseDialog.java @@ -32,7 +32,7 @@ import javax.swing.SwingUtilities; import org.openide.util.NbBundle; import org.openide.windows.WindowManager; import org.sleuthkit.datamodel.HashEntry; -import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase; +import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; /** * @@ -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 hashes = new ArrayList<>(); List 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.getHashSetName()), true); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseProgressDialog.java index 77483e1d42..3f3671c44f 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseProgressDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseProgressDialog.java @@ -33,7 +33,7 @@ import javax.swing.SwingWorker; import org.openide.util.NbBundle; import org.sleuthkit.datamodel.HashEntry; import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase; +import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; /** * @@ -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 hashes; private final List 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(); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java index 0bea515d14..a794ada72d 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java @@ -35,7 +35,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 create a new hash database and add it @@ -47,7 +47,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"; /** @@ -67,7 +67,7 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { * * @return A HashDb object or null. */ - HashDatabase getHashDatabase() { + HashDb getHashDatabase() { return newHashDb; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java index 012544bdab..c281e81db9 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java @@ -36,14 +36,13 @@ 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.optionspanel.AddNewOrganizationDialog; 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.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 @@ -54,7 +53,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 orgs = null; @@ -79,7 +78,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { * * @return A HashDb object or null. */ - HashDatabase getHashDatabase() { + HashDb getHashDatabase() { return selectedHashDb; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java index 55d91b5fbd..75f477b585 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java @@ -36,7 +36,6 @@ 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.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; @@ -48,6 +47,7 @@ import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskException; +import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; @NbBundle.Messages({ "HashDbIngestModule.noKnownBadHashDbSetMsg=No notable hash database set.", @@ -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 knownBadHashSets = new ArrayList<>(); - private List knownHashSets = new ArrayList<>(); + private List knownBadHashSets = new ArrayList<>(); + private List knownHashSets = new ArrayList<>(); private long jobId; private static final HashMap 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 allHashSets, List enabledHashSets) { + private void updateEnabledHashSets(List allHashSets, List 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 knownBadHashSets, List knownHashSets) { + List knownBadHashSets, List knownHashSets) { IngestJobTotals jobTotals = getTotalsForIngestJobs(jobId); totalsForIngestJobs.remove(jobId); @@ -384,7 +384,7 @@ public class HashDbIngestModule implements FileIngestModule { detailsSb.append("

") //NON-NLS .append(NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.complete.databasesUsed")) .append("

\n
    "); //NON-NLS - for (HashDatabase db : knownBadHashSets) { + for (HashDb db : knownBadHashSets) { detailsSb.append("
  • ").append(db.getHashSetName()).append("
  • \n"); //NON-NLS } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index fb2edad967..59dcd998e0 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -61,7 +61,7 @@ public class HashDbManager implements PropertyChangeListener { private static final String HASH_DATABASE_FILE_EXTENSON = "kdb"; //NON-NLS private static HashDbManager instance = null; - private List hashSets = new ArrayList<>(); + private List hashSets = new ArrayList<>(); private Set hashSetNames = new HashSet<>(); private Set hashSetPaths = new HashSet<>(); PropertyChangeSupport changeSupport = new PropertyChangeSupport(HashDbManager.class); @@ -147,15 +147,15 @@ public class HashDbManager implements PropertyChangeListener { * * @throws HashDbManagerException */ - public synchronized HashDb addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException { - HashDb hashDb = null; + public synchronized HashDatabase addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDatabase.KnownFilesType knownFilesType) throws HashDbManagerException { + HashDatabase hashDb = null; hashDb = this.addExistingHashDatabaseNoSave(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType); this.save(); return hashDb; } - synchronized HashDb addExistingHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException { - HashDb hashDb = null; + synchronized HashDatabase addExistingHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDatabase.KnownFilesType knownFilesType) throws HashDbManagerException { + HashDatabase hashDb = null; try { if (!new File(path).exists()) { throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbDoesNotExistExceptionMsg", path)); @@ -194,10 +194,10 @@ public class HashDbManager implements PropertyChangeListener { * * @throws HashDbManagerException */ - public synchronized HashDb addNewHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, - HashDb.KnownFilesType knownFilesType) throws HashDbManagerException { + public synchronized HashDatabase addNewHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, + HashDatabase.KnownFilesType knownFilesType) throws HashDbManagerException { - HashDb hashDb = null; + HashDatabase hashDb = null; hashDb = this.addNewHashDatabaseNoSave(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType); this.save(); @@ -205,9 +205,9 @@ public class HashDbManager implements PropertyChangeListener { return hashDb; } - public synchronized HashDb addNewHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, - HashDb.KnownFilesType knownFilesType) throws HashDbManagerException { - HashDb hashDb = null; + public synchronized HashDatabase addNewHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, + HashDatabase.KnownFilesType knownFilesType) throws HashDbManagerException { + HashDatabase hashDb = null; try { File file = new File(path); if (file.exists()) { @@ -233,9 +233,9 @@ public class HashDbManager implements PropertyChangeListener { return hashDb; } - private HashDb addFileHashDatabase(int handle, String hashSetName, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws TskCoreException { + private HashDatabase addFileHashDatabase(int handle, String hashSetName, boolean searchDuringIngest, boolean sendIngestMessages, HashDatabase.KnownFilesType knownFilesType) throws TskCoreException { // Wrap an object around the handle. - HashDb hashDb = new HashDb(handle, hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType); + HashDatabase hashDb = new HashDatabase(handle, hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType); // Get the indentity data before updating the collections since the // accessor methods may throw. @@ -300,7 +300,7 @@ public class HashDbManager implements PropertyChangeListener { } - synchronized void indexHashDatabase(HashDb hashDb) { + synchronized void indexHashDatabase(HashDatabase hashDb) { hashDb.addPropertyChangeListener(this); HashDbIndexer creator = new HashDbIndexer(hashDb); creator.execute(); @@ -308,8 +308,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(HashDatabase.Event.INDEXING_DONE.name())) { + HashDatabase hashDb = (HashDatabase) event.getNewValue(); if (null != hashDb) { try { String indexPath = hashDb.getIndexPath(); @@ -331,12 +331,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) { @@ -346,36 +346,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; + if(hashDb instanceof HashDatabase){ + HashDatabase hashDatabase = (HashDatabase)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(); + hashDb.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 + 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 @@ -399,16 +399,6 @@ public class HashDbManager implements PropertyChangeListener { throw new HashDbManagerException(NbBundle.getMessage(this.getClass(), "HashDbManager.saveErrorExceptionMsg")); } } - - /** - * Gets all of the HashDbs used to classify files as known or known - * bad. Will not return central repository databases. - * - * @return A list, possibly empty, of hash databases. - */ - public synchronized List getAllHashSets() { - return getAllFileHashSets(); - } /** * Gets all of the file hash databases used to classify files as known or known @@ -416,10 +406,10 @@ public class HashDbManager implements PropertyChangeListener { * * @return A list, possibly empty, of hash databases. */ - synchronized List getAllFileHashSets() { - List hashDbs = new ArrayList<>(); - this.hashSets.stream().filter((thisSet) -> (thisSet instanceof HashDb)).forEach((thisSet) -> { - hashDbs.add((HashDb)thisSet); + synchronized List getAllFileHashSets() { + List hashDbs = new ArrayList<>(); + this.hashSets.stream().filter((thisSet) -> (thisSet instanceof HashDatabase)).forEach((thisSet) -> { + hashDbs.add((HashDatabase)thisSet); }); return hashDbs; } @@ -431,14 +421,14 @@ public class HashDbManager implements PropertyChangeListener { * * @return A list, possibly empty, of hash databases. */ - synchronized List getAllHashDatabases(){ + public synchronized List getAllHashSets(){ try{ updateHashSetsFromCentralRepository(); } catch (TskCoreException ex){ Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS } - List hashDbs = new ArrayList<>(); + List hashDbs = new ArrayList<>(); hashDbs.addAll(this.hashSets); return hashDbs; } @@ -450,24 +440,11 @@ public class HashDbManager implements PropertyChangeListener { */ public synchronized List getKnownFileHashSets() { List 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. - */ - synchronized List getKnownFileHashDatabases() { - List hashDbs = new ArrayList<>(); - this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == HashDb.KnownFilesType.KNOWN)).forEach((db) -> { + this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == HashDatabase.KnownFilesType.KNOWN)).forEach((db) -> { hashDbs.add(db); }); return hashDbs; - } + } /** * Gets all of the hash databases used to classify files as notable. @@ -476,20 +453,7 @@ public class HashDbManager implements PropertyChangeListener { */ public synchronized List getKnownBadFileHashSets() { List 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. - */ - synchronized List getNotableFileHashDatabases() { - List hashDbs = new ArrayList<>(); - this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == HashDb.KnownFilesType.KNOWN_BAD)).forEach((db) -> { + this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == HashDatabase.KnownFilesType.KNOWN_BAD)).forEach((db) -> { hashDbs.add(db); }); return hashDbs; @@ -501,26 +465,12 @@ public class HashDbManager implements PropertyChangeListener { * @return A list, possibly empty, of hash databases. */ public synchronized List getUpdateableHashSets() { - List updateableDbs = new ArrayList<>(); - List 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 getUpdateableHashDatabases(){ return getUpdateableHashSets(this.hashSets); } - private List getUpdateableHashSets(List hashDbs) { - ArrayList updateableDbs = new ArrayList<>(); - for (HashDatabase db : hashDbs) { + private List getUpdateableHashSets(List hashDbs) { + ArrayList updateableDbs = new ArrayList<>(); + for (HashDb db : hashDbs) { try { if (db.isUpdateable()) { updateableDbs.add(db); @@ -542,7 +492,7 @@ 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 = globalSet.getKnownStatus().equals(HashDatabase.KnownFilesType.KNOWN_BAD); crHashSets.add(new HashDbInfo(globalSet.getSetName(), globalSet.getVersion(), globalSet.getGlobalSetID(), globalSet.getKnownStatus(), globalSet.isReadOnly(), false, sendIngestMessages)); } @@ -565,8 +515,8 @@ public class HashDbManager implements PropertyChangeListener { loadHashsetsConfiguration(); } - private void closeHashDatabases(List hashDatabases) { - for (HashDatabase database : hashDatabases) { + private void closeHashDatabases(List hashDatabases) { + for (HashDb database : hashDatabases) { try { database.close(); } catch (TskCoreException ex) { @@ -672,7 +622,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; } @@ -727,7 +677,35 @@ public class HashDbManager implements PropertyChangeListener { return filePath; } - public static interface HashDatabase { + public static interface HashDb { + + /** + * Indicates how files with hashes stored in a particular hash database + * object should be classified. + */ + public enum KnownFilesType { + + KNOWN(NbBundle.getMessage(HashDbManager.class, "HashDbManager.known.text")), + KNOWN_BAD(NbBundle.getMessage(HashDbManager.class, "HashDbManager.knownBad.text")); + private final String displayName; + + private KnownFilesType(String displayName) { + this.displayName = displayName; + } + + public String getDisplayName() { + return this.displayName; + } + } + + /** + * Property change events published by hash database objects. + */ + public enum Event { + + INDEXING_DONE + } + enum DatabaseType{ FILE, CENTRAL_REPOSITORY @@ -739,7 +717,7 @@ public class HashDbManager implements PropertyChangeListener { public String getDatabasePath() throws TskCoreException; - public HashDb.KnownFilesType getKnownFilesType(); + public HashDatabase.KnownFilesType getKnownFilesType(); public boolean getSearchDuringIngest(); @@ -788,6 +766,10 @@ public class HashDbManager implements PropertyChangeListener { public int getHandle(); + public String getIndexPath() throws TskCoreException; + + public boolean hasIndexOnly() throws TskCoreException; + public void firePropertyChange(String propertyName, Object oldValue, Object newValue); public void addPropertyChangeListener(PropertyChangeListener pcl); @@ -808,44 +790,18 @@ public class HashDbManager implements PropertyChangeListener { * 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. - */ - public enum KnownFilesType { - - KNOWN(NbBundle.getMessage(HashDbManager.class, "HashDbManager.known.text")), - KNOWN_BAD(NbBundle.getMessage(HashDbManager.class, "HashDbManager.knownBad.text")); - private final String displayName; - - private KnownFilesType(String displayName) { - this.displayName = displayName; - } - - public String getDisplayName() { - return this.displayName; - } - } - - /** - * Property change events published by hash database objects. - */ - public enum Event { - - INDEXING_DONE - } + public static class HashDatabase implements HashDb{ + private static final long serialVersionUID = 1L; private final int handle; private final String hashSetName; private boolean searchDuringIngest; private boolean sendIngestMessages; - private final HashDb.KnownFilesType knownFilesType; + private final HashDatabase.KnownFilesType knownFilesType; private boolean indexing; private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); - private HashDb(int handle, String hashSetName, boolean useForIngest, boolean sendHitMessages, KnownFilesType knownFilesType) { + private HashDatabase(int handle, String hashSetName, boolean useForIngest, boolean sendHitMessages, KnownFilesType knownFilesType) { this.handle = handle; this.hashSetName = hashSetName; this.searchDuringIngest = useForIngest; @@ -1058,6 +1014,7 @@ public class HashDbManager implements PropertyChangeListener { return SleuthkitJNI.hashDatabaseHasLookupIndex(handle); } + @Override public boolean hasIndexOnly() throws TskCoreException { return SleuthkitJNI.hashDatabaseIsIndexOnly(handle); } @@ -1104,7 +1061,7 @@ public class HashDbManager implements PropertyChangeListener { if (getClass() != obj.getClass()) { return false; } - final HashDb other = (HashDb) obj; + final HashDatabase other = (HashDatabase) obj; if (!Objects.equals(this.hashSetName, other.hashSetName)) { return false; } @@ -1119,13 +1076,13 @@ 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{ + public static class CentralRepoHashDb implements HashDb{ private static final long serialVersionUID = 1L; private final String hashSetName; private boolean searchDuringIngest; private boolean sendIngestMessages; - private final HashDb.KnownFilesType knownFilesType; + private final HashDatabase.KnownFilesType knownFilesType; private final int referenceSetID; private final String version; private String orgName; @@ -1134,7 +1091,7 @@ public class HashDbManager implements PropertyChangeListener { @Messages({"HashDbManager.CentralRepoHashDb.orgError=Error loading organization"}) private CentralRepoHashDb(String hashSetName, String version, int referenceSetID, - boolean useForIngest, boolean sendHitMessages, HashDb.KnownFilesType knownFilesType, + boolean useForIngest, boolean sendHitMessages, HashDatabase.KnownFilesType knownFilesType, boolean readOnly) throws TskCoreException{ this.hashSetName = hashSetName; @@ -1148,7 +1105,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(HashDatabase.class.getName()).log(Level.SEVERE, "Error looking up central repository organization", ex); //NON-NLS orgName = Bundle.HashDbManager_CentralRepoHashDb_orgError(); } } @@ -1178,6 +1135,11 @@ public class HashDbManager implements PropertyChangeListener { public int getHandle(){ return 0; } + + @Override + public boolean hasIndexOnly() throws TskCoreException{ + return true; + } @Override public String getHashSetName() { @@ -1211,12 +1173,13 @@ public class HashDbManager implements PropertyChangeListener { return DatabaseType.CENTRAL_REPOSITORY; } + @Override public String getIndexPath() throws TskCoreException { return ""; } @Override - public HashDb.KnownFilesType getKnownFilesType() { + public HashDatabase.KnownFilesType getKnownFilesType() { return knownFilesType; } @@ -1319,7 +1282,7 @@ public class HashDbManager implements PropertyChangeListener { try{ return EamDb.getInstance().isHashInReferenceSet(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(HashDatabase.class.getName()).log(Level.SEVERE, "Error performing central reposiotry hash lookup", ex); //NON-NLS throw new TskCoreException("Error performing central reposiotry hash lookup", ex); } } @@ -1350,7 +1313,7 @@ public class HashDbManager implements PropertyChangeListener { 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(HashDatabase.class.getName()).log(Level.SEVERE, "Error performing central reposiotry hash lookup", ex); //NON-NLS throw new TskCoreException("Error performing central reposiotry hash lookup", ex); } } @@ -1431,9 +1394,9 @@ public class HashDbManager implements PropertyChangeListener { private class HashDbIndexer extends SwingWorker { private ProgressHandle progress = null; - private HashDb hashDb = null; + private HashDatabase hashDb = null; - HashDbIndexer(HashDb hashDb) { + HashDbIndexer(HashDatabase hashDb) { this.hashDb = hashDb; } @@ -1447,7 +1410,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(HashDatabase.class.getName()).log(Level.SEVERE, "Error indexing hash database", ex); //NON-NLS JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), "HashDbManager.dlgMsg.errorIndexingHashSet", @@ -1477,7 +1440,7 @@ public class HashDbManager implements PropertyChangeListener { } try { - hashDb.firePropertyChange(HashDb.Event.INDEXING_DONE.toString(), null, hashDb); + hashDb.firePropertyChange(HashDatabase.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 diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleFactory.java index 52ae48c8cd..2fb515832b 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleFactory.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleFactory.java @@ -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().getAllHashDatabases()); + return new HashLookupModuleSettings(true, HashDbManager.getInstance().getAllHashSets()); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettings.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettings.java index 9923c7f21b..3e331cb1da 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettings.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettings.java @@ -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 databaseInfoList; - HashLookupModuleSettings(boolean shouldCalculateHashes, List hashDbList){ + HashLookupModuleSettings(boolean shouldCalculateHashes, List 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 enabledHashSets, - List disabledHashSets) { + List enabledHashSets, + List 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,7 +128,7 @@ 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(); @@ -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; diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java index 1e83fb77c6..c6d3e109fe 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java @@ -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; /** @@ -58,13 +58,13 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe } 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, hashDbManager.getKnownFileHashSets(), knownHashSetModels); + initializeHashSetModels(settings, hashDbManager.getKnownBadFileHashSets(), knownBadHashSetModels); } - private void initializeHashSetModels(HashLookupModuleSettings settings, List hashDbs, List hashSetModels) { + private void initializeHashSetModels(HashLookupModuleSettings settings, List hashDbs, List hashSetModels) { hashSetModels.clear(); - for (HashDatabase db : hashDbs) { + for (HashDb db : hashDbs) { hashSetModels.add(new HashSetModel(db, settings.isHashSetEnabled(db), isHashDbValid(db))); } } @@ -105,15 +105,15 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe @Override public IngestModuleIngestJobSettings getSettings() { - List enabledHashSets = new ArrayList<>(); - List disabledHashSets = new ArrayList<>(); + List enabledHashSets = new ArrayList<>(); + List disabledHashSets = new ArrayList<>(); addHashSets(knownHashSetModels, enabledHashSets, disabledHashSets); addHashSets(knownBadHashSetModels, enabledHashSets, disabledHashSets); return new HashLookupModuleSettings(alwaysCalcHashesCheckbox.isSelected(), enabledHashSets, disabledHashSets); } - private void addHashSets(List hashSetModels, List enabledHashSets, List disabledHashSets) { + private void addHashSets(List hashSetModels, List enabledHashSets, List disabledHashSets) { for (HashSetModel model : hashSetModels) { if (model.isEnabled() && model.isValid()) { enabledHashSets.add(model.getDatabase()); @@ -130,19 +130,19 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe } private void updateHashSetModels() { - updateHashSetModels(hashDbManager.getKnownFileHashDatabases(), knownHashSetModels); - updateHashSetModels(hashDbManager.getNotableFileHashDatabases(), knownBadHashSetModels); + updateHashSetModels(hashDbManager.getKnownFileHashSets(), knownHashSetModels); + updateHashSetModels(hashDbManager.getKnownBadFileHashSets(), knownBadHashSetModels); } - void updateHashSetModels(List hashDbs, List hashSetModels) { + void updateHashSetModels(List hashDbs, List hashSetModels) { - List hashDatabases = new ArrayList<>(hashDbs); + List hashDatabases = new ArrayList<>(hashDbs); // Update the hash sets and detect deletions. List 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 +161,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 +173,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 +185,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; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettings.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettings.java index 89d807d507..5dda017e54 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettings.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettings.java @@ -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.HashDb.DatabaseType; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.CentralRepoHashDb; 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 convertHashSetList(List hashSets) throws HashLookupSettingsException{ + static List convertHashSetList(List hashSets) throws HashLookupSettingsException{ List dbInfoList = new ArrayList<>(); - for(HashDbManager.HashDatabase db:hashSets){ + for(HashDbManager.HashDb db:hashSets){ try{ dbInfoList.add(new HashDbInfo(db)); } catch (TskCoreException ex){ @@ -202,7 +202,7 @@ final class HashLookupSettings implements Serializable { // Handle legacy known files types. if (knownFilesType.equals("NSRL")) { //NON-NLS - knownFilesType = HashDbManager.HashDb.KnownFilesType.KNOWN.toString(); + knownFilesType = HashDbManager.HashDatabase.KnownFilesType.KNOWN.toString(); updatedSchema = true; } @@ -236,7 +236,7 @@ final class HashLookupSettings implements Serializable { } else { throw new HashLookupSettingsException(String.format(elementErrorMessage, PATH_ELEMENT)); } - hashDbInfoList.add(new HashDbInfo(hashSetName, HashDbManager.HashDb.KnownFilesType.valueOf(knownFilesType), + hashDbInfoList.add(new HashDbInfo(hashSetName, HashDbManager.HashDatabase.KnownFilesType.valueOf(knownFilesType), searchDuringIngestFlag, sendIngestMessagesFlag, dbPath)); hashSetNames.add(hashSetName); } @@ -299,7 +299,7 @@ final class HashLookupSettings implements Serializable { private static final long serialVersionUID = 1L; private final String hashSetName; - private final HashDbManager.HashDb.KnownFilesType knownFilesType; + private final HashDbManager.HashDatabase.KnownFilesType knownFilesType; private boolean searchDuringIngest; private final boolean sendIngestMessages; private final String path; @@ -318,7 +318,7 @@ final class HashLookupSettings implements Serializable { * @param sendIngestMessages Whether or not ingest messages are sent * @param path The path to the db */ - HashDbInfo(String hashSetName, HashDbManager.HashDb.KnownFilesType knownFilesType, boolean searchDuringIngest, boolean sendIngestMessages, String path) { + HashDbInfo(String hashSetName, HashDbManager.HashDatabase.KnownFilesType knownFilesType, boolean searchDuringIngest, boolean sendIngestMessages, String path) { this.hashSetName = hashSetName; this.knownFilesType = knownFilesType; this.searchDuringIngest = searchDuringIngest; @@ -330,7 +330,7 @@ final class HashLookupSettings implements Serializable { this.dbType = DatabaseType.FILE; } - HashDbInfo(String hashSetName, String version, int referenceSetID, HashDbManager.HashDb.KnownFilesType knownFilesType, boolean readOnly, boolean searchDuringIngest, boolean sendIngestMessages){ + HashDbInfo(String hashSetName, String version, int referenceSetID, HashDbManager.HashDatabase.KnownFilesType knownFilesType, boolean readOnly, boolean searchDuringIngest, boolean sendIngestMessages){ this.hashSetName = hashSetName; this.version = version; this.referenceSetID = referenceSetID; @@ -342,9 +342,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.HashDatabase){ + HashDbManager.HashDatabase fileTypeDb = (HashDbManager.HashDatabase)db; this.hashSetName = fileTypeDb.getHashSetName(); this.knownFilesType = fileTypeDb.getKnownFilesType(); this.searchDuringIngest = fileTypeDb.getSearchDuringIngest(); @@ -402,7 +402,7 @@ final class HashLookupSettings implements Serializable { * * @return The known files type setting. */ - HashDbManager.HashDb.KnownFilesType getKnownFilesType() { + HashDbManager.HashDatabase.KnownFilesType getKnownFilesType() { return knownFilesType; } @@ -457,7 +457,7 @@ final class HashLookupSettings implements Serializable { return dbType == DatabaseType.CENTRAL_REPOSITORY; } - boolean matches(HashDatabase hashDb){ + boolean matches(HashDb hashDb){ if(hashDb == null){ return false; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java index 46b636af82..ef8986af24 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java @@ -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.HashDatabase; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.CentralRepoHashDb; 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 @@ -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 HashDatabase){ + HashDatabase hashDb = (HashDatabase)db; // Disable the central repo fields hashDbVersionLabel.setText(Bundle.HashLookupSettingsPanel_notApplicable()); @@ -304,8 +304,8 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan "HashLookupSettingsPanel.saveFail.title=Save Fail"}) public void saveSettings() { //Checking for for any unindexed databases - List unindexed = new ArrayList<>(); - for (HashDb db : hashSetManager.getAllFileHashSets()) { + List unindexed = new ArrayList<>(); + for (HashDatabase db : hashSetManager.getAllFileHashSets()) { try { if (!db.hasIndex()) { unindexed.add(db); @@ -370,8 +370,8 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan } @Messages({"# {0} - hash lookup name", "HashLookupSettingsPanel.removeDatabaseFailure.message=Failed to remove hash lookup: {0}"}) - void removeThese(List toRemove) { - for (HashDb hashDb : toRemove) { + void removeThese(List toRemove) { + for (HashDatabase hashDb : toRemove) { try { hashSetManager.removeHashDatabaseNoSave(hashDb); } catch (HashDbManager.HashDbManagerException ex) { @@ -389,10 +389,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 unindexed) { + private void showInvalidIndex(boolean plural, List unindexed) { String total = ""; String message; - for (HashDatabase hdb : unindexed) { + for (HashDb hdb : unindexed) { total += "\n" + hdb.getHashSetName(); } if (plural) { @@ -445,7 +445,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan return cellRenderer; } - public HashDatabase getSelection() { + public HashDb getSelection() { return hashSetTableModel.getHashSetAt(getSelectionModel().getMinSelectionIndex()); } @@ -455,7 +455,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan } } - public void selectRowByDatabase(HashDatabase db){ + public void selectRowByDatabase(HashDb db){ setSelection(hashSetTableModel.getIndexByDatabase(db)); } @@ -471,7 +471,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan */ private class HashSetTableModel extends AbstractTableModel { - List hashSets = HashDbManager.getInstance().getAllHashDatabases(); + List hashSets = HashDbManager.getInstance().getAllHashSets(); @Override public int getColumnCount() { @@ -518,7 +518,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 { @@ -526,7 +526,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; @@ -546,7 +546,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan } void refreshModel() { - hashSets = HashDbManager.getInstance().getAllHashDatabases(); + hashSets = HashDbManager.getInstance().getAllHashSets(); refreshDisplay(); } @@ -910,12 +910,12 @@ 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) { hashSetTableModel.refreshModel(); ((HashSetTable) hashSetTable).selectRowByDatabase(hashDb); @@ -924,7 +924,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); @@ -932,18 +932,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 HashDatabase; // Add a listener for the INDEXING_DONE event. This listener will update // the UI. - HashDb hashDb = (HashDb)hashDatabase; + HashDatabase hashDb = (HashDatabase)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(HashDatabase.Event.INDEXING_DONE.toString())) { + HashDb selectedHashDb = ((HashSetTable) hashSetTable).getSelection(); if (selectedHashDb != null && hashDb != null && hashDb.equals(selectedHashDb)) { updateComponents(); } @@ -964,7 +964,7 @@ 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){ int newReferenceSetID = ((CentralRepoHashDb)hashDb).getReferenceSetID(); @@ -985,7 +985,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); @@ -1000,7 +1000,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); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java index 397b4948cf..6f14459eb6 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java @@ -77,7 +77,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P } void importFile(String hashSetName, String version, int orgId, - boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, + boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDatabase.KnownFilesType knownFilesType, boolean readOnly, String importFileName){ setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); @@ -92,7 +92,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 +128,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 implements CentralRepoImportWorker{ @@ -139,7 +139,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P private final int orgId; private final boolean searchDuringIngest; private final boolean sendIngestMessages; - private final HashDbManager.HashDb.KnownFilesType knownFilesType; + private final HashDbManager.HashDatabase.KnownFilesType knownFilesType; private final boolean readOnly; private final File importFile; private final long totalLines; @@ -148,7 +148,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P private final AtomicLong numLines = new AtomicLong(); ImportIDXWorker(String hashSetName, String version, int orgId, - boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, + boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDatabase.KnownFilesType knownFilesType, boolean readOnly, File importFile){ this.hashSetName = hashSetName; @@ -176,7 +176,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P } @Override - public HashDbManager.HashDatabase getDatabase(){ + public HashDbManager.HashDb getDatabase(){ return newHashDb; } @@ -194,7 +194,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P protected Void doInBackground() throws Exception { TskData.FileKnown knownStatus; - if (knownFilesType.equals(HashDbManager.HashDb.KnownFilesType.KNOWN)) { + if (knownFilesType.equals(HashDbManager.HashDatabase.KnownFilesType.KNOWN)) { knownStatus = TskData.FileKnown.KNOWN; } else { knownStatus = TskData.FileKnown.BAD; diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ModalNoButtons.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ModalNoButtons.java index 33f65488d2..5795233479 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ModalNoButtons.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ModalNoButtons.java @@ -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.HashDatabase; /** * 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 unindexed; - HashDb toIndex; + List unindexed; + HashDatabase 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 unindexed) { + ModalNoButtons(HashLookupSettingsPanel hdbmp, java.awt.Frame parent, List 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, HashDatabase 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 remove = new ArrayList<>(); + List 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 (HashDatabase 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(HashDatabase.Event.INDEXING_DONE.name())) { if (currentcount >= length) { this.INDEXING_PROGBAR.setValue(100); this.setModal(false); diff --git a/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDb.java b/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDb.java index 233aad0202..e2c90b005c 100755 --- a/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDb.java +++ b/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDb.java @@ -34,7 +34,7 @@ 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; +import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; /** * 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..."); diff --git a/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDbConfigPanel.form b/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDbConfigPanel.form index 20cec74d82..dfe9ba921e 100755 --- a/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDbConfigPanel.form +++ b/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDbConfigPanel.form @@ -124,7 +124,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDbConfigPanel.java b/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDbConfigPanel.java index 9c1875eeb2..0c20eee562 100644 --- a/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDbConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDbConfigPanel.java @@ -39,7 +39,7 @@ 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; +import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; /** * 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 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 updateableHashSets = HashDbManager.getInstance().getUpdateableHashDatabases(); + List 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 hashSetsComboBox; + private javax.swing.JComboBox hashSetsComboBox; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JScrollPane jScrollPane1; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java index ccb2e49e54..e3f6a23bf5 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java @@ -47,7 +47,7 @@ import org.sleuthkit.autopsy.keywordsearch.KeywordListsManager; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.core.ServicesMonitor; -import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; +import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase; import org.sleuthkit.autopsy.experimental.configuration.AutoIngestSettingsPanel.UpdateConfigSwingWorker; import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CategoryNode; @@ -1017,15 +1017,17 @@ public class SharedConfiguration { // If a copy of the database is loaded, close it before deleting and copying. if (localDb.exists()) { List hashDbs = HashDbManager.getInstance().getAllHashSets(); - HashDbManager.HashDb matchingDb = null; + HashDbManager.HashDatabase matchingDb = null; for (HashDbManager.HashDb db : hashDbs) { - try { - if (localDb.getAbsolutePath().equals(db.getDatabasePath()) || localDb.getAbsolutePath().equals(db.getIndexPath())) { - matchingDb = db; - break; + if(db instanceof HashDbManager.HashDatabase){ + try { + if (localDb.getAbsolutePath().equals(db.getDatabasePath()) || localDb.getAbsolutePath().equals(db.getIndexPath())) { + matchingDb = (HashDbManager.HashDatabase)db; + break; + } + } catch (TskCoreException ex) { + throw new SharedConfigurationException(String.format("Error getting hash database path info for %s", localDb.getParentFile().getAbsolutePath()), ex); } - } catch (TskCoreException ex) { - throw new SharedConfigurationException(String.format("Error getting hash database path info for %s", localDb.getParentFile().getAbsolutePath()), ex); } } @@ -1122,11 +1124,13 @@ public class SharedConfiguration { try { HashDbManager hashDbManager = HashDbManager.getInstance(); hashDbManager.loadLastSavedConfiguration(); - for (HashDb hashDb : hashDbManager.getAllHashSets()) { - if (hashDb.hasIndexOnly()) { - results.add(hashDb.getIndexPath()); - } else { - results.add(hashDb.getDatabasePath()); + for (HashDbManager.HashDb hashDb : hashDbManager.getAllHashSets()) { + if(hashDb instanceof HashDatabase){ + if (hashDb.hasIndexOnly()) { + results.add(hashDb.getIndexPath()); + } else { + results.add(hashDb.getDatabasePath()); + } } } } catch (TskCoreException ex) { From f00ceeea273df66fce95d66bd61e00a118d8577e Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Mon, 13 Nov 2017 14:03:29 -0500 Subject: [PATCH 60/69] Cleanup --- .../autopsy/modules/hashdatabase/AddContentToHashDbAction.java | 2 +- .../modules/hashdatabase/AddHashValuesToDatabaseDialog.java | 2 +- .../hashdatabase/AddHashValuesToDatabaseProgressDialog.java | 2 +- .../modules/hashdatabase/HashDbCreateDatabaseDialog.java | 2 +- .../autopsy/modules/hashdatabase/HashDbIngestModule.java | 2 +- .../autopsy/report/taggedhashes/AddTaggedHashesToHashDb.java | 2 +- .../report/taggedhashes/AddTaggedHashesToHashDbConfigPanel.java | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddContentToHashDbAction.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddContentToHashDbAction.java index effa123af9..5ec70ce3b9 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddContentToHashDbAction.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddContentToHashDbAction.java @@ -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.HashDb; /** * Instances of this Action allow users to content to a hash database. diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseDialog.java index 1fe05701ce..40db15718f 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseDialog.java @@ -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.datamodel.HashEntry; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; +import org.sleuthkit.datamodel.HashEntry; /** * diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseProgressDialog.java index 3f3671c44f..f712a965fd 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseProgressDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseProgressDialog.java @@ -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.HashDb; /** * diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java index a794ada72d..d07f5a034c 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java @@ -33,9 +33,9 @@ import org.openide.windows.WindowManager; 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.HashDb; /** * Instances of this class allow a user to create a new hash database and add it diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java index 75f477b585..40cd2230b3 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java @@ -36,6 +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.HashDb; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; @@ -47,7 +48,6 @@ import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskException; -import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; @NbBundle.Messages({ "HashDbIngestModule.noKnownBadHashDbSetMsg=No notable hash database set.", diff --git a/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDb.java b/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDb.java index e2c90b005c..1de1db7eaa 100755 --- a/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDb.java +++ b/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDb.java @@ -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.HashDb; /** * Instances of this class plug in to the reporting infrastructure to provide a diff --git a/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDbConfigPanel.java b/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDbConfigPanel.java index 0c20eee562..4dd665b890 100644 --- a/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDbConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDbConfigPanel.java @@ -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.HashDb; /** * Instances of this class are used to configure the report module plug in that From 0ea88c0f68213b8ff96544cf764b974e5fec9fc2 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Mon, 13 Nov 2017 14:24:50 -0500 Subject: [PATCH 61/69] Cleanup --- .../modules/hashdatabase/HashDbManager.java | 42 +++++++------------ .../hashdatabase/HashLookupSettingsPanel.java | 15 ++++--- 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index 59dcd998e0..a764065b6b 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -147,15 +147,15 @@ public class HashDbManager implements PropertyChangeListener { * * @throws HashDbManagerException */ - public synchronized HashDatabase addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDatabase.KnownFilesType knownFilesType) throws HashDbManagerException { - HashDatabase hashDb = null; + public synchronized HashDb addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDatabase.KnownFilesType knownFilesType) throws HashDbManagerException { + HashDb hashDb = null; hashDb = this.addExistingHashDatabaseNoSave(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType); this.save(); return hashDb; } - synchronized HashDatabase addExistingHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDatabase.KnownFilesType knownFilesType) throws HashDbManagerException { - HashDatabase hashDb = null; + synchronized HashDb addExistingHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDatabase.KnownFilesType knownFilesType) throws HashDbManagerException { + HashDb hashDb = null; try { if (!new File(path).exists()) { throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbDoesNotExistExceptionMsg", path)); @@ -169,7 +169,7 @@ public class HashDbManager implements PropertyChangeListener { throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.duplicateHashSetNameExceptionMsg", hashSetName)); } - hashDb = addFileHashDatabase(SleuthkitJNI.openHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType); + hashDb = addHashDatabase(SleuthkitJNI.openHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType); } catch (TskCoreException ex) { throw new HashDbManagerException(ex.getMessage()); } @@ -194,10 +194,10 @@ public class HashDbManager implements PropertyChangeListener { * * @throws HashDbManagerException */ - public synchronized HashDatabase addNewHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, - HashDatabase.KnownFilesType knownFilesType) throws HashDbManagerException { + public synchronized HashDb addNewHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, + HashDb.KnownFilesType knownFilesType) throws HashDbManagerException { - HashDatabase hashDb = null; + HashDb hashDb = null; hashDb = this.addNewHashDatabaseNoSave(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType); this.save(); @@ -205,9 +205,9 @@ public class HashDbManager implements PropertyChangeListener { return hashDb; } - public synchronized HashDatabase addNewHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, - HashDatabase.KnownFilesType knownFilesType) throws HashDbManagerException { - HashDatabase hashDb = null; + public synchronized HashDb addNewHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, + HashDb.KnownFilesType knownFilesType) throws HashDbManagerException { + HashDb hashDb = null; try { File file = new File(path); if (file.exists()) { @@ -226,14 +226,14 @@ public class HashDbManager implements PropertyChangeListener { throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.duplicateHashSetNameExceptionMsg", hashSetName)); } - hashDb = addFileHashDatabase(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 HashDatabase addFileHashDatabase(int handle, String hashSetName, boolean searchDuringIngest, boolean sendIngestMessages, HashDatabase.KnownFilesType knownFilesType) throws TskCoreException { + private HashDatabase addHashDatabase(int handle, String hashSetName, boolean searchDuringIngest, boolean sendIngestMessages, HashDatabase.KnownFilesType knownFilesType) throws TskCoreException { // Wrap an object around the handle. HashDatabase hashDb = new HashDatabase(handle, hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType); @@ -400,20 +400,6 @@ public class HashDbManager implements PropertyChangeListener { } } - /** - * Gets all of the file hash databases used to classify files as known or known - * bad. - * - * @return A list, possibly empty, of hash databases. - */ - synchronized List getAllFileHashSets() { - List hashDbs = new ArrayList<>(); - this.hashSets.stream().filter((thisSet) -> (thisSet instanceof HashDatabase)).forEach((thisSet) -> { - hashDbs.add((HashDatabase)thisSet); - }); - return hashDbs; - } - /** * Gets all of the hash databases used to classify files as known or known * bad. Will add any new central repository databases to the list before @@ -551,7 +537,7 @@ public class HashDbManager implements PropertyChangeListener { if(hashDbInfo.isFileDatabaseType()){ String dbPath = this.getValidFilePath(hashDbInfo.getHashSetName(), hashDbInfo.getPath()); if (dbPath != null) { - addFileHashDatabase(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; diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java index ef8986af24..f765fcbd4b 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java @@ -305,13 +305,16 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan public void saveSettings() { //Checking for for any unindexed databases List unindexed = new ArrayList<>(); - for (HashDatabase db : hashSetManager.getAllFileHashSets()) { - try { - if (!db.hasIndex()) { - unindexed.add(db); + for (HashDb db : hashSetManager.getAllHashSets()) { + if(db instanceof HashDatabase){ + try { + HashDatabase hashDatabase = (HashDatabase)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 } - } catch (TskCoreException ex) { - Logger.getLogger(HashLookupSettingsPanel.class.getName()).log(Level.SEVERE, "Error getting index info for hash database", ex); //NON-NLS } } From fed52680a97ec4e4b9a43bf93e7e3f5808344b91 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Mon, 13 Nov 2017 14:28:04 -0500 Subject: [PATCH 62/69] Cleanup --- .../autopsy/modules/hashdatabase/HashDbManager.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index a764065b6b..412fb6410e 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -147,14 +147,14 @@ public class HashDbManager implements PropertyChangeListener { * * @throws HashDbManagerException */ - public synchronized HashDb addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDatabase.KnownFilesType knownFilesType) throws HashDbManagerException { + public synchronized HashDb addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException { HashDb hashDb = null; hashDb = this.addExistingHashDatabaseNoSave(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType); this.save(); return hashDb; } - synchronized HashDb addExistingHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDatabase.KnownFilesType knownFilesType) throws HashDbManagerException { + synchronized HashDb addExistingHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException { HashDb hashDb = null; try { if (!new File(path).exists()) { @@ -407,7 +407,7 @@ public class HashDbManager implements PropertyChangeListener { * * @return A list, possibly empty, of hash databases. */ - public synchronized List getAllHashSets(){ + public synchronized List getAllHashSets() { try{ updateHashSetsFromCentralRepository(); } catch (TskCoreException ex){ From 2bb24e3d4de52068525f1a544fe070dabd82044e Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Tue, 14 Nov 2017 11:32:19 -0500 Subject: [PATCH 63/69] Remove/change some public methods. --- .../datamodel/EamGlobalSet.java | 6 +-- .../modules/hashdatabase/HashDbManager.java | 48 +++++-------------- .../hashdatabase/HashLookupSettings.java | 32 +++++++------ 3 files changed, 31 insertions(+), 55 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalSet.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalSet.java index 80e7d9cb8b..e4292dc6ca 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalSet.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalSet.java @@ -150,11 +150,11 @@ public class EamGlobalSet { * Return the FileKnown status as a KnownFilesType * @return KNOWN or KNOWN_BAD */ - public HashDbManager.HashDatabase.KnownFilesType getKnownStatus(){ + public HashDbManager.HashDb.KnownFilesType getKnownStatus(){ if(fileKnownStatus.equals(TskData.FileKnown.BAD)){ - return HashDbManager.HashDatabase.KnownFilesType.KNOWN_BAD; + return HashDbManager.HashDb.KnownFilesType.KNOWN_BAD; } - return HashDbManager.HashDatabase.KnownFilesType.KNOWN; + return HashDbManager.HashDb.KnownFilesType.KNOWN; } /** diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index 412fb6410e..e656606c52 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -692,11 +692,6 @@ public class HashDbManager implements PropertyChangeListener { INDEXING_DONE } - enum DatabaseType{ - FILE, - CENTRAL_REPOSITORY - }; - public String getHashSetName(); public String getDisplayName(); @@ -709,11 +704,11 @@ public class HashDbManager implements PropertyChangeListener { public boolean getDefaultSearchDuringIngest(); - void setSearchDuringIngest(boolean useForIngest); + public void setSearchDuringIngest(boolean useForIngest); public boolean getSendIngestMessages(); - void setSendIngestMessages(boolean showInboxMessages); + public void setSendIngestMessages(boolean showInboxMessages); /** * Indicates whether the hash database accepts updates. @@ -750,8 +745,6 @@ public class HashDbManager implements PropertyChangeListener { */ public boolean isValid() throws TskCoreException; - public int getHandle(); - public String getIndexPath() throws TskCoreException; public boolean hasIndexOnly() throws TskCoreException; @@ -762,14 +755,11 @@ public class HashDbManager implements PropertyChangeListener { public void removePropertyChangeListener(PropertyChangeListener pcl); - void close() throws TskCoreException; + public void close() throws TskCoreException; @Override public String toString(); - DatabaseType getDatabaseType(); - - } /** @@ -817,8 +807,7 @@ public class HashDbManager implements PropertyChangeListener { propertyChangeSupport.removePropertyChangeListener(pcl); } - @Override - public int getHandle(){ + int getHandle(){ return handle; } @@ -840,12 +829,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); } @@ -996,7 +981,7 @@ public class HashDbManager implements PropertyChangeListener { return hasIndex(); } - public boolean hasIndex() throws TskCoreException { + boolean hasIndex() throws TskCoreException { return SleuthkitJNI.hashDatabaseHasLookupIndex(handle); } @@ -1005,11 +990,11 @@ public class HashDbManager implements PropertyChangeListener { return SleuthkitJNI.hashDatabaseIsIndexOnly(handle); } - public boolean canBeReIndexed() throws TskCoreException { + boolean canBeReIndexed() throws TskCoreException { return SleuthkitJNI.hashDatabaseCanBeReindexed(handle); } - public boolean isIndexing() { + boolean isIndexing() { return indexing; } @@ -1117,11 +1102,6 @@ public class HashDbManager implements PropertyChangeListener { propertyChangeSupport.removePropertyChangeListener(pcl); } - @Override - public int getHandle(){ - return 0; - } - @Override public boolean hasIndexOnly() throws TskCoreException{ return true; @@ -1137,15 +1117,15 @@ public class HashDbManager implements PropertyChangeListener { return getHashSetName() + " " + getVersion(); } - public String getVersion(){ + String getVersion(){ return version; } - public String getOrgName(){ + String getOrgName(){ return orgName; } - public int getReferenceSetID(){ + int getReferenceSetID(){ return referenceSetID; } @@ -1153,11 +1133,6 @@ 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 { @@ -1311,7 +1286,6 @@ 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() { diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettings.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettings.java index 5dda017e54..fecc5ad192 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettings.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettings.java @@ -36,8 +36,8 @@ 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.HashDb.DatabaseType; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.CentralRepoHashDb; +import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase; import org.sleuthkit.datamodel.TskCoreException; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -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.HashDatabase.KnownFilesType knownFilesType; @@ -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 CentralRepoHashDb)) + || (this.dbType == DatabaseType.FILE) && (! (hashDb instanceof HashDatabase))){ 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 CentralRepoHashDb){ + CentralRepoHashDb crDb = (CentralRepoHashDb) hashDb; + if(this.referenceSetID != crDb.getReferenceSetID()){ + return false; + } + + if(! version.equals(crDb.getVersion())){ + return false; + } } return true; From 8a63c5aa154b947d400e84b6ccd8792b0b13141b Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Tue, 14 Nov 2017 15:04:30 -0500 Subject: [PATCH 64/69] Change HashDb interface to an abstract class. Rename SleuthkitHashSet and CentralRepoHashSet --- .../modules/hashdatabase/HashDbManager.java | 158 +++++++++--------- .../hashdatabase/HashLookupSettings.java | 30 ++-- .../hashdatabase/HashLookupSettingsPanel.java | 32 ++-- .../ImportCentralRepoDbProgressDialog.java | 10 +- .../modules/hashdatabase/ModalNoButtons.java | 16 +- .../configuration/SharedConfiguration.java | 28 ++-- 6 files changed, 132 insertions(+), 142 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index e656606c52..4f68120f6a 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -233,9 +233,9 @@ public class HashDbManager implements PropertyChangeListener { return hashDb; } - private HashDatabase addHashDatabase(int handle, String hashSetName, boolean searchDuringIngest, boolean sendIngestMessages, HashDatabase.KnownFilesType knownFilesType) throws TskCoreException { + private SleuthkitHashSet addHashDatabase(int handle, String hashSetName, boolean searchDuringIngest, boolean sendIngestMessages, SleuthkitHashSet.KnownFilesType knownFilesType) throws TskCoreException { // Wrap an object around the handle. - HashDatabase hashDb = new HashDatabase(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. @@ -268,7 +268,7 @@ public class HashDbManager implements PropertyChangeListener { return hashDb; } - 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{ @@ -276,7 +276,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()){ @@ -300,7 +300,7 @@ public class HashDbManager implements PropertyChangeListener { } - synchronized void indexHashDatabase(HashDatabase hashDb) { + synchronized void indexHashDatabase(SleuthkitHashSet hashDb) { hashDb.addPropertyChangeListener(this); HashDbIndexer creator = new HashDbIndexer(hashDb); creator.execute(); @@ -308,8 +308,8 @@ public class HashDbManager implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent event) { - if (event.getPropertyName().equals(HashDatabase.Event.INDEXING_DONE.name())) { - HashDatabase hashDb = (HashDatabase) event.getNewValue(); + if (event.getPropertyName().equals(SleuthkitHashSet.Event.INDEXING_DONE.name())) { + SleuthkitHashSet hashDb = (SleuthkitHashSet) event.getNewValue(); if (null != hashDb) { try { String indexPath = hashDb.getIndexPath(); @@ -352,9 +352,9 @@ public class HashDbManager implements PropertyChangeListener { // Now undertake the operations that could throw. - // Indexing is only relevanet for file type hashsets - if(hashDb instanceof HashDatabase){ - HashDatabase hashDatabase = (HashDatabase)hashDb; + // Indexing is only relevanet for sleuthkit hashsets + if(hashDb instanceof SleuthkitHashSet){ + SleuthkitHashSet hashDatabase = (SleuthkitHashSet)hashDb; try { if(hashDatabase.hasIndex()){ hashSetPaths.remove(hashDatabase.getIndexPath()); @@ -370,12 +370,12 @@ public class HashDbManager implements PropertyChangeListener { } catch (TskCoreException ex) { 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 { - hashDb.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 + 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 @@ -426,7 +426,7 @@ public class HashDbManager implements PropertyChangeListener { */ public synchronized List getKnownFileHashSets() { List hashDbs = new ArrayList<>(); - this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == HashDatabase.KnownFilesType.KNOWN)).forEach((db) -> { + this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == SleuthkitHashSet.KnownFilesType.KNOWN)).forEach((db) -> { hashDbs.add(db); }); return hashDbs; @@ -439,7 +439,7 @@ public class HashDbManager implements PropertyChangeListener { */ public synchronized List getKnownBadFileHashSets() { List hashDbs = new ArrayList<>(); - this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == HashDatabase.KnownFilesType.KNOWN_BAD)).forEach((db) -> { + this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == SleuthkitHashSet.KnownFilesType.KNOWN_BAD)).forEach((db) -> { hashDbs.add(db); }); return hashDbs; @@ -478,7 +478,7 @@ 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(HashDatabase.KnownFilesType.KNOWN_BAD); + boolean sendIngestMessages = globalSet.getKnownStatus().equals(SleuthkitHashSet.KnownFilesType.KNOWN_BAD); crHashSets.add(new HashDbInfo(globalSet.getSetName(), globalSet.getVersion(), globalSet.getGlobalSetID(), globalSet.getKnownStatus(), globalSet.isReadOnly(), false, sendIngestMessages)); } @@ -503,10 +503,12 @@ public class HashDbManager implements PropertyChangeListener { private void closeHashDatabases(List hashDatabases) { for (HashDb 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 + 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(); @@ -663,7 +665,7 @@ public class HashDbManager implements PropertyChangeListener { return filePath; } - public static interface HashDb { + public static abstract class HashDb { /** * Indicates how files with hashes stored in a particular hash database @@ -692,23 +694,23 @@ public class HashDbManager implements PropertyChangeListener { INDEXING_DONE } - public String getHashSetName(); + public abstract String getHashSetName(); - public String getDisplayName(); + abstract String getDisplayName(); - public String getDatabasePath() throws TskCoreException; + public abstract String getDatabasePath() throws TskCoreException; - public HashDatabase.KnownFilesType getKnownFilesType(); + public abstract SleuthkitHashSet.KnownFilesType getKnownFilesType(); - public boolean getSearchDuringIngest(); + public abstract boolean getSearchDuringIngest(); - public boolean getDefaultSearchDuringIngest(); + abstract boolean getDefaultSearchDuringIngest(); - public void setSearchDuringIngest(boolean useForIngest); + abstract void setSearchDuringIngest(boolean useForIngest); - public boolean getSendIngestMessages(); + public abstract boolean getSendIngestMessages(); - public void setSendIngestMessages(boolean showInboxMessages); + abstract void setSendIngestMessages(boolean showInboxMessages); /** * Indicates whether the hash database accepts updates. @@ -717,7 +719,7 @@ public class HashDbManager implements PropertyChangeListener { * * @throws org.sleuthkit.datamodel.TskCoreException */ - public boolean isUpdateable() throws TskCoreException; + public abstract boolean isUpdateable() throws TskCoreException; /** * Adds hashes of content (if calculated) to the hash database. @@ -727,15 +729,15 @@ public class HashDbManager implements PropertyChangeListener { * * @throws TskCoreException */ - public void addHashes(Content content) throws TskCoreException; + public abstract void addHashes(Content content) throws TskCoreException; - public void addHashes(Content content, String comment) throws TskCoreException; + public abstract void addHashes(Content content, String comment) throws TskCoreException; - public void addHashes(List hashes) throws TskCoreException; + public abstract void addHashes(List hashes) throws TskCoreException; - public boolean lookupMD5Quick(Content content) throws TskCoreException; + public abstract boolean lookupMD5Quick(Content content) throws TskCoreException; - public HashHitInfo lookupMD5(Content content) throws TskCoreException; + public abstract HashHitInfo lookupMD5(Content content) throws TskCoreException; /** * Returns whether this database can be enabled. @@ -743,22 +745,20 @@ public class HashDbManager implements PropertyChangeListener { * @return true if is valid, false otherwise * @throws TskCoreException */ - public boolean isValid() throws TskCoreException; + abstract boolean isValid() throws TskCoreException; - public String getIndexPath() throws TskCoreException; + public abstract String getIndexPath() throws TskCoreException; - public boolean hasIndexOnly() throws TskCoreException; + public abstract boolean hasIndexOnly() throws TskCoreException; - public void firePropertyChange(String propertyName, Object oldValue, Object newValue); + public abstract void firePropertyChange(String propertyName, Object oldValue, Object newValue); - public void addPropertyChangeListener(PropertyChangeListener pcl); + public abstract void addPropertyChangeListener(PropertyChangeListener pcl); - public void removePropertyChangeListener(PropertyChangeListener pcl); - - public void close() throws TskCoreException; + public abstract void removePropertyChangeListener(PropertyChangeListener pcl); @Override - public String toString(); + public abstract String toString(); } @@ -766,18 +766,18 @@ public class HashDbManager implements PropertyChangeListener { * Instances of this class represent hash databases used to classify files * as known or know bad. */ - public static class HashDatabase implements HashDb{ + class SleuthkitHashSet extends HashDb{ private static final long serialVersionUID = 1L; private final int handle; private final String hashSetName; private boolean searchDuringIngest; private boolean sendIngestMessages; - private final HashDatabase.KnownFilesType knownFilesType; + private final SleuthkitHashSet.KnownFilesType knownFilesType; private boolean indexing; private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); - private HashDatabase(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; @@ -817,7 +817,7 @@ public class HashDbManager implements PropertyChangeListener { } @Override - public String getDisplayName(){ + String getDisplayName(){ return getHashSetName(); } @@ -846,13 +846,13 @@ public class HashDbManager implements PropertyChangeListener { } @Override - public boolean getDefaultSearchDuringIngest(){ + boolean getDefaultSearchDuringIngest(){ // File type hash sets are on by default return true; } @Override - public void setSearchDuringIngest(boolean useForIngest) { + void setSearchDuringIngest(boolean useForIngest) { this.searchDuringIngest = useForIngest; } @@ -862,7 +862,7 @@ public class HashDbManager implements PropertyChangeListener { } @Override - public void setSendIngestMessages(boolean showInboxMessages) { + void setSendIngestMessages(boolean showInboxMessages) { this.sendIngestMessages = showInboxMessages; } @@ -977,7 +977,7 @@ public class HashDbManager implements PropertyChangeListener { * @throws TskCoreException */ @Override - public boolean isValid() throws TskCoreException { + boolean isValid() throws TskCoreException { return hasIndex(); } @@ -1003,8 +1003,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); } @@ -1032,7 +1031,7 @@ public class HashDbManager implements PropertyChangeListener { if (getClass() != obj.getClass()) { return false; } - final HashDatabase other = (HashDatabase) obj; + final SleuthkitHashSet other = (SleuthkitHashSet) obj; if (!Objects.equals(this.hashSetName, other.hashSetName)) { return false; } @@ -1047,13 +1046,13 @@ 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 HashDb{ + class CentralRepoHashSet extends HashDb{ private static final long serialVersionUID = 1L; private final String hashSetName; private boolean searchDuringIngest; private boolean sendIngestMessages; - private final HashDatabase.KnownFilesType knownFilesType; + private final SleuthkitHashSet.KnownFilesType knownFilesType; private final int referenceSetID; private final String version; private String orgName; @@ -1061,8 +1060,8 @@ 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, - boolean useForIngest, boolean sendHitMessages, HashDatabase.KnownFilesType knownFilesType, + private CentralRepoHashSet(String hashSetName, String version, int referenceSetID, + boolean useForIngest, boolean sendHitMessages, SleuthkitHashSet.KnownFilesType knownFilesType, boolean readOnly) throws TskCoreException{ this.hashSetName = hashSetName; @@ -1076,7 +1075,7 @@ public class HashDbManager implements PropertyChangeListener { try{ orgName = EamDb.getInstance().getReferenceSetOrganization(referenceSetID).getName(); } catch (EamDbException ex){ - Logger.getLogger(HashDatabase.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", ex); //NON-NLS orgName = Bundle.HashDbManager_CentralRepoHashDb_orgError(); } } @@ -1113,7 +1112,7 @@ public class HashDbManager implements PropertyChangeListener { } @Override - public String getDisplayName(){ + String getDisplayName(){ return getHashSetName() + " " + getVersion(); } @@ -1140,7 +1139,7 @@ public class HashDbManager implements PropertyChangeListener { } @Override - public HashDatabase.KnownFilesType getKnownFilesType() { + public SleuthkitHashSet.KnownFilesType getKnownFilesType() { return knownFilesType; } @@ -1150,13 +1149,13 @@ public class HashDbManager implements PropertyChangeListener { } @Override - public boolean getDefaultSearchDuringIngest(){ + boolean getDefaultSearchDuringIngest(){ // Central repo hash sets are off by default return false; } @Override - public void setSearchDuringIngest(boolean useForIngest) { + void setSearchDuringIngest(boolean useForIngest) { this.searchDuringIngest = useForIngest; } @@ -1166,7 +1165,7 @@ public class HashDbManager implements PropertyChangeListener { } @Override - public void setSendIngestMessages(boolean showInboxMessages) { + void setSendIngestMessages(boolean showInboxMessages) { this.sendIngestMessages = showInboxMessages; } @@ -1243,7 +1242,7 @@ public class HashDbManager implements PropertyChangeListener { try{ return EamDb.getInstance().isHashInReferenceSet(file.getMd5Hash(), this.referenceSetID); } catch (EamDbException ex){ - Logger.getLogger(HashDatabase.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", ex); //NON-NLS throw new TskCoreException("Error performing central reposiotry hash lookup", ex); } } @@ -1274,7 +1273,7 @@ public class HashDbManager implements PropertyChangeListener { result = new HashHitInfo(file.getMd5Hash(), "", ""); } } catch (EamDbException ex){ - Logger.getLogger(HashDatabase.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", ex); //NON-NLS throw new TskCoreException("Error performing central reposiotry hash lookup", ex); } } @@ -1288,14 +1287,14 @@ public class HashDbManager implements PropertyChangeListener { * @return true if is valid, false otherwise */ @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; } } @@ -1304,11 +1303,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(){ @@ -1334,7 +1328,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; } @@ -1354,9 +1348,9 @@ public class HashDbManager implements PropertyChangeListener { private class HashDbIndexer extends SwingWorker { private ProgressHandle progress = null; - private HashDatabase hashDb = null; + private SleuthkitHashSet hashDb = null; - HashDbIndexer(HashDatabase hashDb) { + HashDbIndexer(SleuthkitHashSet hashDb) { this.hashDb = hashDb; } @@ -1370,7 +1364,7 @@ public class HashDbManager implements PropertyChangeListener { try { SleuthkitJNI.createLookupIndexForHashDatabase(hashDb.getHandle()); } catch (TskCoreException ex) { - Logger.getLogger(HashDatabase.class.getName()).log(Level.SEVERE, "Error indexing hash database", ex); //NON-NLS + Logger.getLogger(SleuthkitHashSet.class.getName()).log(Level.SEVERE, "Error indexing hash database", ex); //NON-NLS JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), "HashDbManager.dlgMsg.errorIndexingHashSet", @@ -1400,7 +1394,7 @@ public class HashDbManager implements PropertyChangeListener { } try { - hashDb.firePropertyChange(HashDatabase.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 diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettings.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettings.java index fecc5ad192..8630b516c4 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettings.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettings.java @@ -36,8 +36,8 @@ 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.CentralRepoHashDb; -import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase; +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; @@ -202,7 +202,7 @@ final class HashLookupSettings implements Serializable { // Handle legacy known files types. if (knownFilesType.equals("NSRL")) { //NON-NLS - knownFilesType = HashDbManager.HashDatabase.KnownFilesType.KNOWN.toString(); + knownFilesType = HashDbManager.SleuthkitHashSet.KnownFilesType.KNOWN.toString(); updatedSchema = true; } @@ -236,7 +236,7 @@ final class HashLookupSettings implements Serializable { } else { throw new HashLookupSettingsException(String.format(elementErrorMessage, PATH_ELEMENT)); } - hashDbInfoList.add(new HashDbInfo(hashSetName, HashDbManager.HashDatabase.KnownFilesType.valueOf(knownFilesType), + hashDbInfoList.add(new HashDbInfo(hashSetName, HashDbManager.SleuthkitHashSet.KnownFilesType.valueOf(knownFilesType), searchDuringIngestFlag, sendIngestMessagesFlag, dbPath)); hashSetNames.add(hashSetName); } @@ -304,7 +304,7 @@ final class HashLookupSettings implements Serializable { private static final long serialVersionUID = 1L; private final String hashSetName; - private final HashDbManager.HashDatabase.KnownFilesType knownFilesType; + private final HashDbManager.SleuthkitHashSet.KnownFilesType knownFilesType; private boolean searchDuringIngest; private final boolean sendIngestMessages; private final String path; @@ -323,7 +323,7 @@ final class HashLookupSettings implements Serializable { * @param sendIngestMessages Whether or not ingest messages are sent * @param path The path to the db */ - HashDbInfo(String hashSetName, HashDbManager.HashDatabase.KnownFilesType knownFilesType, boolean searchDuringIngest, boolean sendIngestMessages, String path) { + HashDbInfo(String hashSetName, HashDbManager.SleuthkitHashSet.KnownFilesType knownFilesType, boolean searchDuringIngest, boolean sendIngestMessages, String path) { this.hashSetName = hashSetName; this.knownFilesType = knownFilesType; this.searchDuringIngest = searchDuringIngest; @@ -335,7 +335,7 @@ final class HashLookupSettings implements Serializable { this.dbType = DatabaseType.FILE; } - HashDbInfo(String hashSetName, String version, int referenceSetID, HashDbManager.HashDatabase.KnownFilesType knownFilesType, boolean readOnly, boolean searchDuringIngest, boolean sendIngestMessages){ + HashDbInfo(String hashSetName, String version, int referenceSetID, HashDbManager.SleuthkitHashSet.KnownFilesType knownFilesType, boolean readOnly, boolean searchDuringIngest, boolean sendIngestMessages){ this.hashSetName = hashSetName; this.version = version; this.referenceSetID = referenceSetID; @@ -348,8 +348,8 @@ final class HashLookupSettings implements Serializable { } HashDbInfo(HashDbManager.HashDb db) throws TskCoreException{ - if(db instanceof HashDbManager.HashDatabase){ - HashDbManager.HashDatabase fileTypeDb = (HashDbManager.HashDatabase)db; + if(db instanceof HashDbManager.SleuthkitHashSet){ + HashDbManager.SleuthkitHashSet fileTypeDb = (HashDbManager.SleuthkitHashSet)db; this.hashSetName = fileTypeDb.getHashSetName(); this.knownFilesType = fileTypeDb.getKnownFilesType(); this.searchDuringIngest = fileTypeDb.getSearchDuringIngest(); @@ -364,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(); @@ -407,7 +407,7 @@ final class HashLookupSettings implements Serializable { * * @return The known files type setting. */ - HashDbManager.HashDatabase.KnownFilesType getKnownFilesType() { + HashDbManager.SleuthkitHashSet.KnownFilesType getKnownFilesType() { return knownFilesType; } @@ -471,8 +471,8 @@ final class HashLookupSettings implements Serializable { return false; } - if((this.dbType == DatabaseType.CENTRAL_REPOSITORY) && (! (hashDb instanceof CentralRepoHashDb)) - || (this.dbType == DatabaseType.FILE) && (! (hashDb instanceof HashDatabase))){ + if((this.dbType == DatabaseType.CENTRAL_REPOSITORY) && (! (hashDb instanceof CentralRepoHashSet)) + || (this.dbType == DatabaseType.FILE) && (! (hashDb instanceof SleuthkitHashSet))){ return false; } @@ -480,8 +480,8 @@ final class HashLookupSettings implements Serializable { return false; } - if(hashDb instanceof CentralRepoHashDb){ - CentralRepoHashDb crDb = (CentralRepoHashDb) hashDb; + if(hashDb instanceof CentralRepoHashSet){ + CentralRepoHashSet crDb = (CentralRepoHashSet) hashDb; if(this.referenceSetID != crDb.getReferenceSetID()){ return false; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java index f765fcbd4b..d4a77883d6 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java @@ -45,8 +45,8 @@ 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.HashDatabase; -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.HashDb; @@ -180,8 +180,8 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan addHashesToDatabaseButton.setEnabled(false); } - if(db instanceof HashDatabase){ - HashDatabase hashDb = (HashDatabase)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()); @@ -304,11 +304,11 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan "HashLookupSettingsPanel.saveFail.title=Save Fail"}) public void saveSettings() { //Checking for for any unindexed databases - List unindexed = new ArrayList<>(); + List unindexed = new ArrayList<>(); for (HashDb db : hashSetManager.getAllHashSets()) { - if(db instanceof HashDatabase){ + if(db instanceof SleuthkitHashSet){ try { - HashDatabase hashDatabase = (HashDatabase)db; + SleuthkitHashSet hashDatabase = (SleuthkitHashSet)db; if (!hashDatabase.hasIndex()) { unindexed.add(hashDatabase); } @@ -373,8 +373,8 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan } @Messages({"# {0} - hash lookup name", "HashLookupSettingsPanel.removeDatabaseFailure.message=Failed to remove hash lookup: {0}"}) - void removeThese(List toRemove) { - for (HashDatabase hashDb : toRemove) { + void removeThese(List toRemove) { + for (SleuthkitHashSet hashDb : toRemove) { try { hashSetManager.removeHashDatabaseNoSave(hashDb); } catch (HashDbManager.HashDbManagerException ex) { @@ -392,7 +392,7 @@ 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 unindexed) { + private void showInvalidIndex(boolean plural, List unindexed) { String total = ""; String message; for (HashDb hdb : unindexed) { @@ -937,15 +937,15 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan private void indexButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_indexButtonActionPerformed final HashDb hashDatabase = ((HashSetTable) hashSetTable).getSelection(); assert hashDatabase != null; - assert hashDatabase instanceof HashDatabase; + assert hashDatabase instanceof SleuthkitHashSet; // Add a listener for the INDEXING_DONE event. This listener will update // the UI. - HashDatabase hashDb = (HashDatabase)hashDatabase; + SleuthkitHashSet hashDb = (SleuthkitHashSet)hashDatabase; hashDb.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { - if (evt.getPropertyName().equals(HashDatabase.Event.INDEXING_DONE.toString())) { + if (evt.getPropertyName().equals(SleuthkitHashSet.Event.INDEXING_DONE.toString())) { HashDb selectedHashDb = ((HashSetTable) hashSetTable).getSelection(); if (selectedHashDb != null && hashDb != null && hashDb.equals(selectedHashDb)) { updateComponents(); @@ -969,8 +969,8 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan private void importDatabaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importDatabaseButtonActionPerformed HashDb hashDb = new HashDbImportDatabaseDialog().getHashDatabase(); if (null != hashDb) { - if(hashDb instanceof CentralRepoHashDb){ - int newReferenceSetID = ((CentralRepoHashDb)hashDb).getReferenceSetID(); + if(hashDb instanceof CentralRepoHashSet){ + int newReferenceSetID = ((CentralRepoHashSet)hashDb).getReferenceSetID(); newReferenceSetIDs.add(newReferenceSetID); } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java index 6f14459eb6..1f44df404e 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java @@ -77,7 +77,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P } void importFile(String hashSetName, String version, int orgId, - boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDatabase.KnownFilesType knownFilesType, + boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.SleuthkitHashSet.KnownFilesType knownFilesType, boolean readOnly, String importFileName){ setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); @@ -139,16 +139,16 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P private final int orgId; private final boolean searchDuringIngest; private final boolean sendIngestMessages; - private final HashDbManager.HashDatabase.KnownFilesType knownFilesType; + private final HashDbManager.SleuthkitHashSet.KnownFilesType knownFilesType; private final boolean readOnly; 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, - boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDatabase.KnownFilesType knownFilesType, + boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.SleuthkitHashSet.KnownFilesType knownFilesType, boolean readOnly, File importFile){ this.hashSetName = hashSetName; @@ -194,7 +194,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P protected Void doInBackground() throws Exception { TskData.FileKnown knownStatus; - if (knownFilesType.equals(HashDbManager.HashDatabase.KnownFilesType.KNOWN)) { + if (knownFilesType.equals(HashDbManager.SleuthkitHashSet.KnownFilesType.KNOWN)) { knownStatus = TskData.FileKnown.KNOWN; } else { knownStatus = TskData.FileKnown.BAD; diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ModalNoButtons.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ModalNoButtons.java index 5795233479..41a9fe4fe8 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ModalNoButtons.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ModalNoButtons.java @@ -26,7 +26,7 @@ import java.util.List; import javax.swing.JOptionPane; import org.openide.util.NbBundle; -import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase; +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.HashDatabase; */ class ModalNoButtons extends javax.swing.JDialog implements PropertyChangeListener { - List unindexed; - HashDatabase toIndex; + List 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 unindexed) { + ModalNoButtons(HashLookupSettingsPanel hdbmp, java.awt.Frame parent, List 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, HashDatabase 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 remove = new ArrayList<>(); + List 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 (HashDatabase 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(HashDatabase.Event.INDEXING_DONE.name())) { + if (evt.getPropertyName().equals(SleuthkitHashSet.Event.INDEXING_DONE.name())) { if (currentcount >= length) { this.INDEXING_PROGBAR.setValue(100); this.setModal(false); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java index e3f6a23bf5..1720b4b647 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java @@ -47,7 +47,7 @@ import org.sleuthkit.autopsy.keywordsearch.KeywordListsManager; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.core.ServicesMonitor; -import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDatabase; +import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; import org.sleuthkit.autopsy.experimental.configuration.AutoIngestSettingsPanel.UpdateConfigSwingWorker; import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CategoryNode; @@ -1017,17 +1017,15 @@ public class SharedConfiguration { // If a copy of the database is loaded, close it before deleting and copying. if (localDb.exists()) { List hashDbs = HashDbManager.getInstance().getAllHashSets(); - HashDbManager.HashDatabase matchingDb = null; + HashDbManager.HashDb matchingDb = null; for (HashDbManager.HashDb db : hashDbs) { - if(db instanceof HashDbManager.HashDatabase){ - try { - if (localDb.getAbsolutePath().equals(db.getDatabasePath()) || localDb.getAbsolutePath().equals(db.getIndexPath())) { - matchingDb = (HashDbManager.HashDatabase)db; - break; - } - } catch (TskCoreException ex) { - throw new SharedConfigurationException(String.format("Error getting hash database path info for %s", localDb.getParentFile().getAbsolutePath()), ex); + try { + if (localDb.getAbsolutePath().equals(db.getDatabasePath()) || localDb.getAbsolutePath().equals(db.getIndexPath())) { + matchingDb = db; + break; } + } catch (TskCoreException ex) { + throw new SharedConfigurationException(String.format("Error getting hash database path info for %s", localDb.getParentFile().getAbsolutePath()), ex); } } @@ -1125,12 +1123,10 @@ public class SharedConfiguration { HashDbManager hashDbManager = HashDbManager.getInstance(); hashDbManager.loadLastSavedConfiguration(); for (HashDbManager.HashDb hashDb : hashDbManager.getAllHashSets()) { - if(hashDb instanceof HashDatabase){ - if (hashDb.hasIndexOnly()) { - results.add(hashDb.getIndexPath()); - } else { - results.add(hashDb.getDatabasePath()); - } + if (hashDb.hasIndexOnly()) { + results.add(hashDb.getIndexPath()); + } else { + results.add(hashDb.getDatabasePath()); } } } catch (TskCoreException ex) { From 156970c9e51b64dcad976b64a52aceac67118f91 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Wed, 15 Nov 2017 09:08:29 -0500 Subject: [PATCH 65/69] Made reference set methods less hash-specific --- .../datamodel/AbstractSqlEamDb.java | 40 +++++++++++++------ .../centralrepository/datamodel/EamDb.java | 15 ++++++- .../datamodel/SqliteEamDb.java | 4 +- .../modules/hashdatabase/HashDbManager.java | 4 +- 4 files changed, 45 insertions(+), 18 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index fad0196288..5fba1f1670 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -1251,13 +1251,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); } @@ -1285,16 +1285,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 files 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 { @@ -1312,29 +1314,43 @@ public abstract class AbstractSqlEamDb implements EamDb { /** * Check whether the given reference set exists in the central repository. * @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 hash is found in the reference set + */ + @Override + public boolean isValueInReferenceSet(String value, int referenceSetID, int correlationTypeID) throws EamDbException{ Connection conn = connect(); @@ -1343,11 +1359,11 @@ 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(); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java index 4edeb5b734..1f1bd8a942 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java @@ -380,12 +380,23 @@ public interface EamDb { public boolean referenceSetExists(String hashSetName, 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? diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java index 45a0388561..4ee57db0b2 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java @@ -657,10 +657,10 @@ 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(); } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index 4f68120f6a..27935cc3d9 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -1240,7 +1240,7 @@ 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(SleuthkitHashSet.class.getName()).log(Level.SEVERE, "Error performing central reposiotry hash lookup", ex); //NON-NLS throw new TskCoreException("Error performing central reposiotry hash lookup", ex); @@ -1268,7 +1268,7 @@ 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(), "", ""); } From 143e530c327f32f51ecaab3779ecb8ac203ff050 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Wed, 15 Nov 2017 09:18:03 -0500 Subject: [PATCH 66/69] Missed a "hash" reference --- .../autopsy/centralrepository/datamodel/AbstractSqlEamDb.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index 5fba1f1670..fa03d01321 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -1347,7 +1347,7 @@ public abstract class AbstractSqlEamDb implements EamDb { * @param value * @param referenceSetID * @param correlationTypeID - * @return true if the hash is found in the reference set + * @return true if the value is found in the reference set */ @Override public boolean isValueInReferenceSet(String value, int referenceSetID, int correlationTypeID) throws EamDbException{ From 61b7f89788ad9aa42fe412874dddb8f8cde24f85 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Thu, 16 Nov 2017 09:40:29 -0500 Subject: [PATCH 67/69] Cleanup --- .../datamodel/AbstractSqlEamDb.java | 13 +++++++------ .../autopsy/centralrepository/datamodel/EamDb.java | 14 ++++++++------ .../centralrepository/datamodel/SqliteEamDb.java | 9 +++++---- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index fa03d01321..eb73f9ef66 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -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; @@ -1312,7 +1311,8 @@ 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 setName * @param version @@ -1773,14 +1773,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; @@ -1789,7 +1790,7 @@ 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()); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java index 1f1bd8a942..2ab708e5de 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java @@ -361,23 +361,25 @@ public interface EamDb { 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 file hash is in this reference set. diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java index 4ee57db0b2..efbda95156 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java @@ -667,17 +667,18 @@ public class SqliteEamDb extends AbstractSqlEamDb { } /** - * 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(); } From c062a20213a3fcddcd0d8d37b66b4fc9bfa80657 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Fri, 17 Nov 2017 08:47:43 -0500 Subject: [PATCH 68/69] Addresses most of the review comments --- .../datamodel/AbstractSqlEamDb.java | 39 ++++--------------- .../centralrepository/datamodel/EamDb.java | 19 ++------- .../datamodel/EamGlobalSet.java | 32 +++++++++------ .../datamodel/SqliteEamDb.java | 10 ++--- .../modules/hashdatabase/HashDbManager.java | 38 +++++++++++------- .../hashdatabase/HashLookupSettings.java | 12 +++--- .../ImportCentralRepoDbProgressDialog.java | 11 +++--- 7 files changed, 72 insertions(+), 89 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index eb73f9ef66..7c7d22066e 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -1276,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,7 +1285,7 @@ public abstract class AbstractSqlEamDb implements EamDb { /** * Remove all entries for this reference set from the reference tables - * (Currently only removes entries from the files table) + * (Currently only removes entries from the reference_file table) * @param referenceSetID * @throws EamDbException */ @@ -1303,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); @@ -1369,7 +1369,7 @@ public abstract class AbstractSqlEamDb implements EamDb { 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); @@ -1388,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) { @@ -1537,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. @@ -1634,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; @@ -1796,7 +1772,8 @@ public abstract class AbstractSqlEamDb implements EamDb { 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); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java index 2ab708e5de..9f7e31fbc5 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java @@ -354,7 +354,7 @@ public interface EamDb { List 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 */ @@ -408,7 +408,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 @@ -477,20 +477,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 diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalSet.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalSet.java index e4292dc6ca..23a4c257ae 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalSet.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalSet.java @@ -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 diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java index efbda95156..719a58385b 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java @@ -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 */ @@ -693,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(); } @@ -786,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(); } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index 27935cc3d9..35dd424c39 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -52,6 +52,7 @@ import org.sleuthkit.datamodel.HashEntry; import org.sleuthkit.datamodel.HashHitInfo; import org.sleuthkit.datamodel.SleuthkitJNI; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; /** * This class implements a singleton that manages the set of hash databases used @@ -233,7 +234,7 @@ public class HashDbManager implements PropertyChangeListener { return hashDb; } - private SleuthkitHashSet addHashDatabase(int handle, String hashSetName, boolean searchDuringIngest, boolean sendIngestMessages, SleuthkitHashSet.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. SleuthkitHashSet hashDb = new SleuthkitHashSet(handle, hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType); @@ -426,7 +427,7 @@ public class HashDbManager implements PropertyChangeListener { */ public synchronized List getKnownFileHashSets() { List hashDbs = new ArrayList<>(); - this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == SleuthkitHashSet.KnownFilesType.KNOWN)).forEach((db) -> { + this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == HashDb.KnownFilesType.KNOWN)).forEach((db) -> { hashDbs.add(db); }); return hashDbs; @@ -439,7 +440,7 @@ public class HashDbManager implements PropertyChangeListener { */ public synchronized List getKnownBadFileHashSets() { List hashDbs = new ArrayList<>(); - this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == SleuthkitHashSet.KnownFilesType.KNOWN_BAD)).forEach((db) -> { + this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == HashDb.KnownFilesType.KNOWN_BAD)).forEach((db) -> { hashDbs.add(db); }); return hashDbs; @@ -478,9 +479,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(SleuthkitHashSet.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 @@ -488,6 +489,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 @@ -700,7 +708,7 @@ public class HashDbManager implements PropertyChangeListener { public abstract String getDatabasePath() throws TskCoreException; - public abstract SleuthkitHashSet.KnownFilesType getKnownFilesType(); + public abstract HashDb.KnownFilesType getKnownFilesType(); public abstract boolean getSearchDuringIngest(); @@ -773,7 +781,7 @@ public class HashDbManager implements PropertyChangeListener { private final String hashSetName; private boolean searchDuringIngest; private boolean sendIngestMessages; - private final SleuthkitHashSet.KnownFilesType knownFilesType; + private final HashDb.KnownFilesType knownFilesType; private boolean indexing; private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); @@ -1052,7 +1060,7 @@ public class HashDbManager implements PropertyChangeListener { private final String hashSetName; private boolean searchDuringIngest; private boolean sendIngestMessages; - private final SleuthkitHashSet.KnownFilesType knownFilesType; + private final HashDb.KnownFilesType knownFilesType; private final int referenceSetID; private final String version; private String orgName; @@ -1061,7 +1069,7 @@ public class HashDbManager implements PropertyChangeListener { @Messages({"HashDbManager.CentralRepoHashDb.orgError=Error loading organization"}) private CentralRepoHashSet(String hashSetName, String version, int referenceSetID, - boolean useForIngest, boolean sendHitMessages, SleuthkitHashSet.KnownFilesType knownFilesType, + boolean useForIngest, boolean sendHitMessages, HashDb.KnownFilesType knownFilesType, boolean readOnly) throws TskCoreException{ this.hashSetName = hashSetName; @@ -1075,7 +1083,7 @@ public class HashDbManager implements PropertyChangeListener { try{ orgName = EamDb.getInstance().getReferenceSetOrganization(referenceSetID).getName(); } catch (EamDbException ex){ - Logger.getLogger(SleuthkitHashSet.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(); } } @@ -1139,7 +1147,7 @@ public class HashDbManager implements PropertyChangeListener { } @Override - public SleuthkitHashSet.KnownFilesType getKnownFilesType() { + public HashDb.KnownFilesType getKnownFilesType() { return knownFilesType; } @@ -1242,7 +1250,8 @@ public class HashDbManager implements PropertyChangeListener { try{ return EamDb.getInstance().isFileHashInReferenceSet(file.getMd5Hash(), this.referenceSetID); } catch (EamDbException ex){ - Logger.getLogger(SleuthkitHashSet.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); } } @@ -1273,7 +1282,8 @@ public class HashDbManager implements PropertyChangeListener { result = new HashHitInfo(file.getMd5Hash(), "", ""); } } catch (EamDbException ex){ - Logger.getLogger(SleuthkitHashSet.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); } } @@ -1364,7 +1374,7 @@ public class HashDbManager implements PropertyChangeListener { try { SleuthkitJNI.createLookupIndexForHashDatabase(hashDb.getHandle()); } catch (TskCoreException ex) { - Logger.getLogger(SleuthkitHashSet.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", diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettings.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettings.java index 8630b516c4..948f18451d 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettings.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettings.java @@ -202,7 +202,7 @@ final class HashLookupSettings implements Serializable { // Handle legacy known files types. if (knownFilesType.equals("NSRL")) { //NON-NLS - knownFilesType = HashDbManager.SleuthkitHashSet.KnownFilesType.KNOWN.toString(); + knownFilesType = HashDbManager.HashDb.KnownFilesType.KNOWN.toString(); updatedSchema = true; } @@ -236,7 +236,7 @@ final class HashLookupSettings implements Serializable { } else { throw new HashLookupSettingsException(String.format(elementErrorMessage, PATH_ELEMENT)); } - hashDbInfoList.add(new HashDbInfo(hashSetName, HashDbManager.SleuthkitHashSet.KnownFilesType.valueOf(knownFilesType), + hashDbInfoList.add(new HashDbInfo(hashSetName, HashDbManager.HashDb.KnownFilesType.valueOf(knownFilesType), searchDuringIngestFlag, sendIngestMessagesFlag, dbPath)); hashSetNames.add(hashSetName); } @@ -304,7 +304,7 @@ final class HashLookupSettings implements Serializable { private static final long serialVersionUID = 1L; private final String hashSetName; - private final HashDbManager.SleuthkitHashSet.KnownFilesType knownFilesType; + private final HashDbManager.HashDb.KnownFilesType knownFilesType; private boolean searchDuringIngest; private final boolean sendIngestMessages; private final String path; @@ -323,7 +323,7 @@ final class HashLookupSettings implements Serializable { * @param sendIngestMessages Whether or not ingest messages are sent * @param path The path to the db */ - HashDbInfo(String hashSetName, HashDbManager.SleuthkitHashSet.KnownFilesType knownFilesType, boolean searchDuringIngest, boolean sendIngestMessages, String path) { + HashDbInfo(String hashSetName, HashDbManager.HashDb.KnownFilesType knownFilesType, boolean searchDuringIngest, boolean sendIngestMessages, String path) { this.hashSetName = hashSetName; this.knownFilesType = knownFilesType; this.searchDuringIngest = searchDuringIngest; @@ -335,7 +335,7 @@ final class HashLookupSettings implements Serializable { this.dbType = DatabaseType.FILE; } - HashDbInfo(String hashSetName, String version, int referenceSetID, HashDbManager.SleuthkitHashSet.KnownFilesType knownFilesType, boolean readOnly, boolean searchDuringIngest, boolean sendIngestMessages){ + HashDbInfo(String hashSetName, String version, int referenceSetID, HashDbManager.HashDb.KnownFilesType knownFilesType, boolean readOnly, boolean searchDuringIngest, boolean sendIngestMessages){ this.hashSetName = hashSetName; this.version = version; this.referenceSetID = referenceSetID; @@ -407,7 +407,7 @@ final class HashLookupSettings implements Serializable { * * @return The known files type setting. */ - HashDbManager.SleuthkitHashSet.KnownFilesType getKnownFilesType() { + HashDbManager.HashDb.KnownFilesType getKnownFilesType() { return knownFilesType; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java index 1f44df404e..880feabcb7 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java @@ -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; @@ -77,7 +78,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P } void importFile(String hashSetName, String version, int orgId, - boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.SleuthkitHashSet.KnownFilesType knownFilesType, + boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, boolean readOnly, String importFileName){ setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); @@ -139,7 +140,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P private final int orgId; private final boolean searchDuringIngest; private final boolean sendIngestMessages; - private final HashDbManager.SleuthkitHashSet.KnownFilesType knownFilesType; + private final HashDbManager.HashDb.KnownFilesType knownFilesType; private final boolean readOnly; private final File importFile; private final long totalLines; @@ -148,7 +149,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P private final AtomicLong numLines = new AtomicLong(); ImportIDXWorker(String hashSetName, String version, int orgId, - boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.SleuthkitHashSet.KnownFilesType knownFilesType, + boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, boolean readOnly, File importFile){ this.hashSetName = hashSetName; @@ -194,14 +195,14 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P protected Void doInBackground() throws Exception { TskData.FileKnown knownStatus; - if (knownFilesType.equals(HashDbManager.SleuthkitHashSet.KnownFilesType.KNOWN)) { + if (knownFilesType.equals(HashDbManager.HashDb.KnownFilesType.KNOWN)) { knownStatus = TskData.FileKnown.KNOWN; } else { knownStatus = TskData.FileKnown.BAD; } // 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 From 5bccb82c685882dab0523fc93de5642957aff3b7 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Fri, 17 Nov 2017 09:41:37 -0500 Subject: [PATCH 69/69] Update central repo hashsets automatically when getting known, known bad, or updateable hash sets --- .../modules/hashdatabase/HashDbManager.java | 17 ++++++++++++++++- .../HashLookupModuleSettingsPanel.java | 5 ----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index 35dd424c39..e8de1893ca 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -427,6 +427,11 @@ public class HashDbManager implements PropertyChangeListener { */ public synchronized List getKnownFileHashSets() { List 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); }); @@ -440,6 +445,11 @@ public class HashDbManager implements PropertyChangeListener { */ public synchronized List getKnownBadFileHashSets() { List 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); }); @@ -457,6 +467,11 @@ public class HashDbManager implements PropertyChangeListener { private List getUpdateableHashSets(List hashDbs) { ArrayList 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()) { @@ -603,7 +618,7 @@ public class HashDbManager implements PropertyChangeListener { } } - void updateHashSetsFromCentralRepository() throws TskCoreException { + private void updateHashSetsFromCentralRepository() throws TskCoreException { if(EamDb.isEnabled()){ List crHashDbInfoList = getCentralRepoHashSetsFromDatabase(); for(HashDbInfo hashDbInfo : crHashDbInfoList) { diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java index c6d3e109fe..bbe2a4e7d9 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java @@ -53,11 +53,6 @@ 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.getKnownFileHashSets(), knownHashSetModels); initializeHashSetModels(settings, hashDbManager.getKnownBadFileHashSets(), knownBadHashSetModels); }