diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml
index 25e17dd3eb..987b2ffe78 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
+
+
+
@@ -269,6 +309,7 @@
org.sleuthkit.autopsy.eventsorg.sleuthkit.autopsy.externalresultsorg.sleuthkit.autopsy.filesearch
+ org.sleuthkit.autopsy.guiutilsorg.sleuthkit.autopsy.ingestorg.sleuthkit.autopsy.keywordsearchserviceorg.sleuthkit.autopsy.menuactions
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..60db8edaf8 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
@@ -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..66e983b1ce 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;
/**
@@ -45,13 +44,16 @@ import org.sleuthkit.autopsy.coreutils.Logger;
final class CaseDeleteAction extends CallableSystemAction {
private static final long serialVersionUID = 1L;
- private static final Logger logger = Logger.getLogger(CaseDeleteAction.class.getName());
+ private static final Logger LOGGER = Logger.getLogger(CaseDeleteAction.class.getName());
CaseDeleteAction() {
putValue(Action.NAME, NbBundle.getMessage(CaseDeleteAction.class, "CTL_CaseDeleteAction"));
this.setEnabled(false);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), (PropertyChangeEvent evt) -> {
- setEnabled(null != evt.getNewValue() && UserPreferences.getMode() != UserPreferences.SelectedMode.REVIEW);
+ /*
+ * A value of 'null' signifies that there is no case open.
+ */
+ setEnabled(null != evt.getNewValue());
});
}
@@ -93,7 +95,7 @@ final class CaseDeleteAction extends CallableSystemAction {
try {
get();
} catch (InterruptedException | ExecutionException ex) {
- logger.log(Level.SEVERE, String.format("Failed to delete case %s at %s", caseName, caseDirectory), ex);
+ LOGGER.log(Level.SEVERE, String.format("Failed to delete case %s at %s", caseName, caseDirectory), ex);
JOptionPane.showMessageDialog(
null,
Bundle.Case_deleteCaseFailureMessageBox_message(ex.getLocalizedMessage()),
@@ -108,7 +110,7 @@ final class CaseDeleteAction extends CallableSystemAction {
}.execute();
}
} catch (IllegalStateException ex) {
- logger.log(Level.SEVERE, "Case delete action called with no current case", ex);
+ LOGGER.log(Level.SEVERE, "Case delete action called with no current case", ex);
}
}
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..7a12b69cf7
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenMultiUserAction.java
@@ -0,0 +1,91 @@
+/*
+ * 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.event.ActionEvent;
+import java.awt.event.ActionListener;
+import javax.swing.JDialog;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionRegistration;
+import org.openide.util.HelpCtx;
+import org.openide.util.NbBundle;
+import org.openide.util.actions.CallableSystemAction;
+import org.openide.windows.WindowManager;
+import org.sleuthkit.autopsy.core.UserPreferences;
+
+/**
+ * The action associated with the Open Multi-User Case menu item via the
+ * layer.xml file.
+ *
+ * This action should only be invoked in the event dispatch thread (EDT).
+ */
+@ActionID(category = "Case", id = "org.sleuthkit.autopsy.casemodule.CaseOpenMultiUserAction")
+@ActionReference(path = "Menu/Case", position = 102)
+@ActionRegistration(displayName = "#CTL_CaseOpenMultiUserAction", lazy = false)
+@NbBundle.Messages({"CTL_CaseOpenMultiUserAction=Open Multi-User Case"})
+public final class CaseOpenMultiUserAction extends CallableSystemAction implements ActionListener {
+
+ private static final long serialVersionUID = 1L;
+ private static JDialog multiUserCaseWindow;
+
+ private static final String DISPLAY_NAME = Bundle.CTL_CaseOpenMultiUserAction();
+
+ public CaseOpenMultiUserAction() {}
+
+ @Override
+ public boolean isEnabled() {
+ return UserPreferences.getIsMultiUserModeEnabled();
+ }
+
+ /**
+ * Pops up a case selection panel to allow the user to select a multi-user
+ * case to open.
+ *
+ * @param event The action event.
+ */
+ @Override
+ public void actionPerformed(ActionEvent event) {
+ if(multiUserCaseWindow == null) {
+ multiUserCaseWindow = MultiUserCasesDialog.getInstance();
+ }
+ multiUserCaseWindow.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
+ multiUserCaseWindow.setVisible(true);
+ }
+
+ @Override
+ public void performAction() {
+ actionPerformed(null);
+ }
+
+ @Override
+ public String getName() {
+ return DISPLAY_NAME;
+ }
+
+ @Override
+ public HelpCtx getHelpCtx() {
+ return HelpCtx.DEFAULT_HELP;
+ }
+
+ @Override
+ public boolean asynchronous() {
+ return false; // run on edt
+ }
+}
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..2c81d100e4 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,11 @@ import org.sleuthkit.autopsy.coreutils.NetworkUtils;
public class CueBannerPanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L;
- private static final String LOCAL_HOST_NAME = NetworkUtils.getLocalHostName();
- private static final String REVIEW_MODE_TITLE = "Cases" + " (" + LOCAL_HOST_NAME + ")";
/*
* This is field is static for the sake of the closeOpenRecentCasesWindow
* method.
*/
private static JDialog recentCasesWindow;
- private static JDialog autoIngestCasePanelWindow;
public static void closeOpenRecentCasesWindow() {
if (null != recentCasesWindow) {
@@ -56,15 +50,9 @@ public class CueBannerPanel extends javax.swing.JPanel {
}
}
- public static void closeAutoIngestCasesWindow() {
- if (null != autoIngestCasePanelWindow) {
- autoIngestCasePanelWindow.setVisible(false);
- }
- }
-
public CueBannerPanel() {
initComponents();
- customizeComponents();
+ initRecentCasesWindow();
enableComponents();
}
@@ -75,7 +63,7 @@ public class CueBannerPanel extends javax.swing.JPanel {
ImageIcon icon = new ImageIcon(cl.getResource(welcomeLogo));
autopsyLogo.setIcon(icon);
}
- customizeComponents();
+ initRecentCasesWindow();
enableComponents();
}
@@ -90,11 +78,6 @@ public class CueBannerPanel extends javax.swing.JPanel {
public void refresh() {
enableComponents();
}
-
- private void customizeComponents() {
- initRecentCasesWindow();
- initAutoIngestCasesWindow();
- }
private void initRecentCasesWindow() {
recentCasesWindow = new JDialog(
@@ -118,39 +101,15 @@ public class CueBannerPanel extends javax.swing.JPanel {
recentCasesWindow.pack();
recentCasesWindow.setResizable(false);
}
-
- private void initAutoIngestCasesWindow() {
- autoIngestCasePanelWindow = new JDialog(
- WindowManager.getDefault().getMainWindow(),
- REVIEW_MODE_TITLE,
- Dialog.ModalityType.APPLICATION_MODAL);
- autoIngestCasePanelWindow.getRootPane().registerKeyboardAction(
- e -> {
- autoIngestCasePanelWindow.setVisible(false);
- },
- KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);
- OpenRecentCasePanel recentCasesPanel = OpenRecentCasePanel.getInstance();
- recentCasesPanel.setCloseButtonActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- autoIngestCasePanelWindow.setVisible(false);
- }
- });
- AutoIngestCasePanelInterface autoIngestCasePanel = Lookup.getDefault().lookup(AutoIngestCasePanelInterface.class);
- autoIngestCasePanel.addWindowStateListener(autoIngestCasePanelWindow);
- autoIngestCasePanelWindow.add((JPanel)autoIngestCasePanel);
- autoIngestCasePanelWindow.pack();
- autoIngestCasePanelWindow.setResizable(false);
- }
private void enableComponents() {
boolean enableOpenRecentCaseButton = (RecentCases.getInstance().getTotalRecentCases() > 0);
openRecentCaseButton.setEnabled(enableOpenRecentCaseButton);
openRecentCaseLabel.setEnabled(enableOpenRecentCaseButton);
- boolean showOpenAutoIngestCaseButton = (UserPreferences.getMode() == UserPreferences.SelectedMode.REVIEW);
- openAutoIngestCaseButton.setVisible(showOpenAutoIngestCaseButton);
- openAutoIngestCaseLabel.setVisible(showOpenAutoIngestCaseButton);
+ boolean enableOpenMultiUserCaseButton = UserPreferences.getIsMultiUserModeEnabled();
+ openMultiUserCaseButton.setEnabled(enableOpenMultiUserCaseButton);
+ openMultiUserCaseLabel.setEnabled(enableOpenMultiUserCaseButton);
}
/**
@@ -172,8 +131,8 @@ public class CueBannerPanel extends javax.swing.JPanel {
openExistingCaseLabel = new javax.swing.JLabel();
closeButton = new javax.swing.JButton();
jSeparator1 = new javax.swing.JSeparator();
- openAutoIngestCaseButton = new javax.swing.JButton();
- openAutoIngestCaseLabel = new javax.swing.JLabel();
+ openMultiUserCaseButton = new javax.swing.JButton();
+ openMultiUserCaseLabel = new javax.swing.JLabel();
autopsyLogo.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/casemodule/welcome_logo.png"))); // NOI18N
autopsyLogo.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.autopsyLogo.text")); // NOI18N
@@ -229,21 +188,21 @@ public class CueBannerPanel extends javax.swing.JPanel {
jSeparator1.setOrientation(javax.swing.SwingConstants.VERTICAL);
- openAutoIngestCaseButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/casemodule/btn_icon_open_existing.png"))); // NOI18N
- openAutoIngestCaseButton.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.openAutoIngestCaseButton.text")); // NOI18N
- openAutoIngestCaseButton.setBorder(null);
- openAutoIngestCaseButton.setBorderPainted(false);
- openAutoIngestCaseButton.setContentAreaFilled(false);
- openAutoIngestCaseButton.setMargin(new java.awt.Insets(1, 1, 1, 1));
- openAutoIngestCaseButton.setPreferredSize(new java.awt.Dimension(64, 64));
- openAutoIngestCaseButton.addActionListener(new java.awt.event.ActionListener() {
+ openMultiUserCaseButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/casemodule/btn_icon_open_existing.png"))); // NOI18N
+ openMultiUserCaseButton.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.openMultiUserCaseButton.text")); // NOI18N
+ openMultiUserCaseButton.setBorder(null);
+ openMultiUserCaseButton.setBorderPainted(false);
+ openMultiUserCaseButton.setContentAreaFilled(false);
+ openMultiUserCaseButton.setMargin(new java.awt.Insets(1, 1, 1, 1));
+ openMultiUserCaseButton.setPreferredSize(new java.awt.Dimension(64, 64));
+ openMultiUserCaseButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
- openAutoIngestCaseButtonActionPerformed(evt);
+ openMultiUserCaseButtonActionPerformed(evt);
}
});
- openAutoIngestCaseLabel.setFont(openAutoIngestCaseLabel.getFont().deriveFont(openAutoIngestCaseLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 13));
- openAutoIngestCaseLabel.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.openAutoIngestCaseLabel.text")); // NOI18N
+ openMultiUserCaseLabel.setFont(openMultiUserCaseLabel.getFont().deriveFont(openMultiUserCaseLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 13));
+ openMultiUserCaseLabel.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.openMultiUserCaseLabel.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
@@ -261,13 +220,13 @@ public class CueBannerPanel extends javax.swing.JPanel {
.addComponent(createNewCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(openRecentCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(openExistingCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addComponent(openAutoIngestCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addComponent(openMultiUserCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(createNewCaseLabel)
.addComponent(openRecentCaseLabel)
.addComponent(openExistingCaseLabel)
- .addComponent(openAutoIngestCaseLabel)))
+ .addComponent(openMultiUserCaseLabel)))
.addComponent(closeButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 73, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);
@@ -290,9 +249,9 @@ public class CueBannerPanel extends javax.swing.JPanel {
.addComponent(openExistingCaseLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(openAutoIngestCaseButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 58, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(openMultiUserCaseButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 58, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
- .addComponent(openAutoIngestCaseLabel)
+ .addComponent(openMultiUserCaseLabel)
.addGap(20, 20, 20))))
.addComponent(jSeparator1)
.addComponent(autopsyLogo, javax.swing.GroupLayout.PREFERRED_SIZE, 257, javax.swing.GroupLayout.PREFERRED_SIZE))
@@ -316,10 +275,11 @@ public class CueBannerPanel extends javax.swing.JPanel {
recentCasesWindow.setVisible(true);
}//GEN-LAST:event_openRecentCaseButtonActionPerformed
- private void openAutoIngestCaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openAutoIngestCaseButtonActionPerformed
- autoIngestCasePanelWindow.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
- autoIngestCasePanelWindow.setVisible(true);
- }//GEN-LAST:event_openAutoIngestCaseButtonActionPerformed
+ private void openMultiUserCaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openMultiUserCaseButtonActionPerformed
+ MultiUserCasesDialog multiUserCaseWindow = MultiUserCasesDialog.getInstance();
+ multiUserCaseWindow.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
+ multiUserCaseWindow.setVisible(true);
+ }//GEN-LAST:event_openMultiUserCaseButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel autopsyLogo;
@@ -327,8 +287,8 @@ public class CueBannerPanel extends javax.swing.JPanel {
private javax.swing.JButton createNewCaseButton;
private javax.swing.JLabel createNewCaseLabel;
private javax.swing.JSeparator jSeparator1;
- private javax.swing.JButton openAutoIngestCaseButton;
- private javax.swing.JLabel openAutoIngestCaseLabel;
+ private javax.swing.JButton openMultiUserCaseButton;
+ private javax.swing.JLabel openMultiUserCaseLabel;
private javax.swing.JButton openExistingCaseButton;
private javax.swing.JLabel openExistingCaseLabel;
private javax.swing.JButton openRecentCaseButton;
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..bedc09d799
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java
@@ -0,0 +1,442 @@
+/*
+ * 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.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
+import java.util.logging.Level;
+import org.sleuthkit.autopsy.coordinationservice.CaseNodeData;
+import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
+import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
+import org.sleuthkit.autopsy.coreutils.Logger;
+
+/**
+ * Handles locating and opening multi-user cases.
+ */
+final class MultiUserCaseManager {
+
+ private static final Logger LOGGER = Logger.getLogger(MultiUserCaseManager.class.getName());
+ private static final String ALERT_FILE_NAME = "autoingest.alert";
+ private static MultiUserCaseManager instance;
+ private CoordinationService coordinationService;
+
+ /**
+ * Gets the multi-user case manager.
+ *
+ * @return The multi-user case manager singleton.
+ *
+ * @throws MultiUserCaseManagerException
+ */
+ synchronized static MultiUserCaseManager getInstance() throws MultiUserCaseManager.MultiUserCaseManagerException {
+ if (null == instance) {
+ instance = new MultiUserCaseManager();
+ }
+ return instance;
+ }
+
+ /**
+ * Constructs an object that handles locating and opening multi-user cases.
+ *
+ * @throws MultiUserCaseManagerException
+ */
+ private MultiUserCaseManager() throws MultiUserCaseManagerException {
+ try {
+ coordinationService = CoordinationService.getInstance();
+ } catch (CoordinationServiceException ex) {
+ throw new MultiUserCaseManager.MultiUserCaseManagerException("Failed to get the coordination service.", ex);
+ }
+ }
+
+ /**
+ * Gets a list of the cases in the top level case folder
+ *
+ * @return List of cases.
+ *
+ * @throws CoordinationServiceException
+ */
+ List 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()) {
+ /*
+ * Search for '*.aut' and 'autoingest.alert' files.
+ */
+ File[] fileArray = caseFolder.listFiles();
+ if (fileArray == null) {
+ continue;
+ }
+ String autFilePath = null;
+ boolean alertFileFound = false;
+ for (File file : fileArray) {
+ String name = file.getName().toLowerCase();
+ if (autFilePath == null && name.endsWith(".aut")) {
+ autFilePath = file.getAbsolutePath();
+ if (!alertFileFound) {
+ continue;
+ }
+ }
+ if (!alertFileFound && name.endsWith(ALERT_FILE_NAME)) {
+ alertFileFound = true;
+ }
+ if (autFilePath != null && alertFileFound) {
+ break;
+ }
+ }
+
+ if (autFilePath != null) {
+ try {
+ CaseStatus caseStatus;
+ if (alertFileFound) {
+ /*
+ * When an alert file exists, ignore the node data
+ * and use the ALERT status.
+ */
+ caseStatus = CaseStatus.ALERT;
+ } else {
+ byte[] rawData = coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, node);
+ if (rawData != null && rawData.length > 0) {
+ /*
+ * When node data exists, use the status stored
+ * in the node data.
+ */
+ CaseNodeData caseNodeData = new CaseNodeData(rawData);
+ if (caseNodeData.getErrorsOccurred()) {
+ caseStatus = CaseStatus.ALERT;
+ } else {
+ caseStatus = CaseStatus.OK;
+ }
+ } else {
+ /*
+ * When no node data is available, use the 'OK'
+ * status to avoid confusing the end-user.
+ */
+ caseStatus = CaseStatus.OK;
+ }
+ }
+
+ CaseMetadata caseMetadata = new CaseMetadata(Paths.get(autFilePath));
+ cases.add(new MultiUserCase(casePath, caseMetadata, caseStatus));
+ } catch (CaseMetadata.CaseMetadataException | MultiUserCase.MultiUserCaseException ex) {
+ LOGGER.log(Level.SEVERE, String.format("Error reading case metadata file '%s'.", autFilePath), ex);
+ } catch (InterruptedException | CaseNodeData.InvalidDataException ex) {
+ LOGGER.log(Level.SEVERE, String.format("Error reading case node data for '%s'.", node), ex);
+ }
+ }
+ }
+ }
+ return cases;
+ }
+
+ /**
+ * Opens a multi-user case.
+ *
+ * @param caseMetadataFilePath Path to the case metadata file.
+ *
+ * @throws CaseActionException
+ */
+ synchronized void openCase(Path caseMetadataFilePath) throws CaseActionException {
+ /*
+ * Open the case.
+ */
+ Case.openAsCurrentCase(caseMetadataFilePath.toString());
+ }
+
+ /**
+ * Exception type thrown when there is an error completing a multi-user case
+ * manager operation.
+ */
+ static final class MultiUserCaseManagerException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructs an instance of the exception type thrown when there is an
+ * error completing a multi-user case manager operation.
+ *
+ * @param message The exception message.
+ */
+ private MultiUserCaseManagerException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs an instance of the exception type thrown when there is an
+ * error completing a multi-user case manager operation.
+ *
+ * @param message The exception message.
+ * @param cause A Throwable cause for the error.
+ */
+ private MultiUserCaseManagerException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ }
+
+ /**
+ * A representation of a multi-user case.
+ */
+ static class MultiUserCase implements Comparable {
+
+ private final Path caseDirectoryPath;
+ private final String caseDisplayName;
+ private final String metadataFileName;
+ private final Date createDate;
+ private final Date lastAccessedDate;
+ private CaseStatus status;
+
+ /**
+ * Constructs a representation of a multi-user case
+ *
+ * @param caseDirectoryPath The case directory path.
+ * @param caseMetadata The case metadata.
+ *
+ * @throws MultiUserCaseException If no case metadata (.aut) file is
+ * found in the case directory.
+ */
+ MultiUserCase(Path caseDirectoryPath, CaseMetadata caseMetadata, CaseStatus status) throws MultiUserCaseException {
+ this.caseDirectoryPath = caseDirectoryPath;
+ caseDisplayName = caseMetadata.getCaseDisplayName();
+ metadataFileName = caseMetadata.getFilePath().getFileName().toString();
+ this.status = status;
+ BasicFileAttributes fileAttrs = null;
+ try {
+ fileAttrs = Files.readAttributes(Paths.get(caseDirectoryPath.toString(), metadataFileName), BasicFileAttributes.class);
+ } catch (IOException ex) {
+ LOGGER.log(Level.SEVERE, String.format("Error reading file attributes of case metadata file in %s, will use current time for case createDate/lastModfiedDate", caseDirectoryPath), ex);
+ }
+ if (null != fileAttrs) {
+ createDate = new Date(fileAttrs.creationTime().toMillis());
+ lastAccessedDate = new Date(fileAttrs.lastAccessTime().toMillis());
+ } else {
+ createDate = new Date();
+ lastAccessedDate = new Date();
+ }
+ }
+
+ /**
+ * Gets the case directory path.
+ *
+ * @return The case directory path.
+ */
+ Path getCaseDirectoryPath() {
+ return this.caseDirectoryPath;
+ }
+
+ /**
+ * Gets the case display name. This may differ from the name supplied to
+ * the directory or metadata file names if a case has been renamed.
+ *
+ * @return The case display name.
+ */
+ String getCaseDisplayName() {
+ return this.caseDisplayName;
+ }
+
+ /**
+ * Gets the creation date for the case, defined as the create time of
+ * the case metadata file.
+ *
+ * @return The case creation date.
+ */
+ Date getCreationDate() {
+ return this.createDate;
+ }
+
+ /**
+ * Gets the last accessed date for the case, defined as the last
+ * accessed time of the case metadata file.
+ *
+ * @return The last accessed date.
+ */
+ Date getLastAccessedDate() {
+ return this.lastAccessedDate;
+ }
+
+ /**
+ * Gets metadata (.aut) file name.
+ *
+ * @return The metadata file name.
+ */
+ String getMetadataFileName() {
+ return this.metadataFileName;
+ }
+
+ /**
+ * Gets the status of this case.
+ *
+ * @return See CaseStatus enum definition.
+ */
+ CaseStatus getStatus() {
+ return status;
+ }
+
+ /**
+ * Gets the case metadata from a case directory path.
+ *
+ * @param caseDirectoryPath The case directory path.
+ *
+ * @return Case metadata.
+ *
+ * @throws CaseMetadata.CaseMetadataException If the CaseMetadata object
+ * cannot be constructed.
+ * @throws MultiUserCaseException If no case metadata (.aut)
+ * file is found in the case
+ * directory.
+ */
+ private CaseMetadata getCaseMetadataFromCaseDirectoryPath(Path caseDirectoryPath) throws CaseMetadata.CaseMetadataException, MultiUserCaseException {
+ CaseMetadata caseMetadata = null;
+
+ File directory = new File(caseDirectoryPath.toString());
+ if (directory.isDirectory()) {
+ File autFile = null;
+
+ /*
+ * Attempt to find an AUT file via a directory scan.
+ */
+ for (File file : directory.listFiles()) {
+ if (file.getName().toLowerCase().endsWith(CaseMetadata.getFileExtension()) && file.isFile()) {
+ autFile = file;
+ break;
+ }
+ }
+
+ if (autFile == null || !autFile.isFile()) {
+ throw new MultiUserCaseException(String.format("No case metadata (.aut) file found in the case directory '%s'.", caseDirectoryPath.toString()));
+ }
+
+ caseMetadata = new CaseMetadata(Paths.get(autFile.getAbsolutePath()));
+ }
+
+ return caseMetadata;
+ }
+
+ /**
+ * Indicates whether or not some other object is "equal to" this
+ * MultiUserCase object.
+ *
+ * @param other The other object.
+ *
+ * @return True or false.
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof MultiUserCase)) {
+ return false;
+ }
+ if (other == this) {
+ return true;
+ }
+ return this.caseDirectoryPath.toString().equals(((MultiUserCase) other).caseDirectoryPath.toString());
+ }
+
+ /**
+ * Returns a hash code value for this MultiUserCase object.
+ *
+ * @return The has code.
+ */
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 71 * hash + Objects.hashCode(this.caseDirectoryPath);
+ hash = 71 * hash + Objects.hashCode(this.createDate);
+ hash = 71 * hash + Objects.hashCode(this.caseDisplayName);
+ return hash;
+ }
+
+ /**
+ * Compares this MultiUserCase object with another MultiUserCase object
+ * for order.
+ */
+ @Override
+ public int compareTo(MultiUserCase other) {
+ return -this.lastAccessedDate.compareTo(other.getLastAccessedDate());
+ }
+
+ /**
+ * Comparator for a descending order sort on date created.
+ */
+ static class LastAccessedDateDescendingComparator implements Comparator {
+
+ /**
+ * 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
new file mode 100755
index 0000000000..8c90aeccb4
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesDialog.java
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+final class MultiUserCasesDialog extends JDialog {
+
+ private static final long serialVersionUID = 1L;
+ private static final String REVIEW_MODE_TITLE = "Open Multi-User Case";
+ private static MultiUserCasesPanel multiUserCasesPanel;
+ private static MultiUserCasesDialog instance;
+
+ /**
+ * Gets the instance of the MultiuserCasesDialog.
+ *
+ * @return The instance.
+ */
+ static public MultiUserCasesDialog getInstance() {
+ if(instance == null) {
+ instance = new MultiUserCasesDialog();
+ instance.init();
+ }
+ return instance;
+ }
+
+ /**
+ * Constructs a MultiUserCasesDialog object.
+ */
+ private MultiUserCasesDialog() {
+ super(WindowManager.getDefault().getMainWindow(),
+ REVIEW_MODE_TITLE,
+ Dialog.ModalityType.APPLICATION_MODAL);
+ }
+
+ /**
+ * Initializes the multi-user cases panel.
+ */
+ private void init() {
+ getRootPane().registerKeyboardAction(
+ e -> {
+ setVisible(false);
+ },
+ KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);
+
+ multiUserCasesPanel = new MultiUserCasesPanel(this);
+ add(multiUserCasesPanel);
+ pack();
+ setResizable(false);
+ }
+
+ /**
+ * Set the dialog visibility. When setting it to visible, the contents will
+ * refresh.
+ *
+ * @param value True or false.
+ */
+ @Override
+ public void setVisible(boolean value) {
+ if(value) {
+ multiUserCasesPanel.refresh();
+ }
+ super.setVisible(value);
+ }
+}
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form
similarity index 83%
rename from Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.form
rename to Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form
index cb0f275809..18d99fa0dc 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 @@
-
+
@@ -99,11 +99,9 @@
-
-
@@ -118,7 +116,7 @@
-
+
@@ -153,7 +151,7 @@
-
+
@@ -165,10 +163,10 @@
-
+
-
+
@@ -182,7 +180,7 @@
-
+
@@ -196,7 +194,7 @@
-
+
@@ -209,7 +207,7 @@
-
+
@@ -222,7 +220,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..d0676e1966 100755
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java
@@ -16,52 +16,42 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.experimental.autoingest;
+package org.sleuthkit.autopsy.casemodule;
import java.awt.Cursor;
import java.awt.Desktop;
-import java.awt.EventQueue;
-import java.awt.event.ActionEvent;
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.ArrayList;
import java.util.Date;
import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.SwingWorker;
+import javax.swing.RowSorter;
+import javax.swing.SortOrder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
-import org.openide.util.NbBundle;
-import org.openide.util.lookup.ServiceProvider;
-import org.openide.windows.WindowManager;
-import org.sleuthkit.autopsy.casemodule.CaseActionCancelledException;
-import org.sleuthkit.autopsy.casemodule.CaseMetadata;
-import org.sleuthkit.autopsy.casemodule.StartupWindowProvider;
+import javax.swing.table.TableRowSorter;
+import org.sleuthkit.autopsy.casemodule.MultiUserCaseManager.MultiUserCase;
+import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coreutils.Logger;
+import org.sleuthkit.autopsy.guiutils.LongDateCellRenderer;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
-import org.sleuthkit.autopsy.casemodule.AutoIngestCasePanelInterface;
-import org.sleuthkit.autopsy.casemodule.CueBannerPanel;
-import org.sleuthkit.autopsy.coreutils.NetworkUtils;
-import org.sleuthkit.autopsy.experimental.configuration.StartupWindow;
+import org.sleuthkit.autopsy.guiutils.GrayableCellRenderer;
+import org.sleuthkit.autopsy.guiutils.StatusIconCellRenderer;
/**
* A panel that allows a user to open cases created by auto ingest.
*/
-@ServiceProvider(service = AutoIngestCasePanelInterface.class)
-public final class AutoIngestCasePanel extends JPanel implements AutoIngestCasePanelInterface {
+final class MultiUserCasesPanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L;
- private static final Logger logger = Logger.getLogger(AutoIngestCasePanel.class.getName());
- private static final AutoIngestCase.LastAccessedDateDescendingComparator reverseDateModifiedComparator = new AutoIngestCase.LastAccessedDateDescendingComparator();
+ private static final Logger LOGGER = Logger.getLogger(MultiUserCasesPanel.class.getName());
+ private static final String LOG_FILE_NAME = "auto_ingest_log.txt";
+ private static final MultiUserCaseManager.MultiUserCase.LastAccessedDateDescendingComparator REVERSE_DATE_MODIFIED_COMPARATOR = new MultiUserCaseManager.MultiUserCase.LastAccessedDateDescendingComparator();
private static final int CASE_COL_MIN_WIDTH = 30;
private static final int CASE_COL_MAX_WIDTH = 2000;
private static final int CASE_COL_PREFERRED_WIDTH = 300;
@@ -71,9 +61,6 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
private static final int STATUS_COL_MIN_WIDTH = 55;
private static final int STATUS_COL_MAX_WIDTH = 250;
private static final int STATUS_COL_PREFERRED_WIDTH = 60;
- private static final int MILLIS_TO_WAIT_BEFORE_STARTING = 500;
- private static final int MILLIS_TO_WAIT_BETWEEN_UPDATES = 300000;
- private ScheduledThreadPoolExecutor casesTableRefreshExecutor;
/*
* The JTable table model for the cases table presented by this view is
@@ -82,11 +69,12 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
* TODO (RC): Consider unifying this stuff in an enum as in
* AutoIngestDashboard to make it less error prone.
*/
- private static final String CASE_HEADER = org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.CaseHeaderText");
- private static final String CREATEDTIME_HEADER = org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.CreatedTimeHeaderText");
- private static final String COMPLETEDTIME_HEADER = org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.LastAccessedTimeHeaderText");
- private static final String STATUS_ICON_HEADER = org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.StatusIconHeaderText");
- private static final String OUTPUT_FOLDER_HEADER = org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.OutputFolderHeaderText");
+ private static final String CASE_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.CaseHeaderText");
+ private static final String CREATEDTIME_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.CreatedTimeHeaderText");
+ private static final String COMPLETEDTIME_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.LastAccessedTimeHeaderText");
+ private static final String STATUS_ICON_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.StatusIconHeaderText");
+ private static final String OUTPUT_FOLDER_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.OutputFolderHeaderText");
+ private static final String METADATA_FILE_HEADER = org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.MetadataFileHeaderText");
enum COLUMN_HEADERS {
@@ -94,51 +82,20 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
CREATEDTIME,
COMPLETEDTIME,
STATUS_ICON,
- OUTPUTFOLDER
+ OUTPUTFOLDER,
+ METADATA_FILE
}
- private final String[] columnNames = {CASE_HEADER, CREATEDTIME_HEADER, COMPLETEDTIME_HEADER, STATUS_ICON_HEADER, OUTPUT_FOLDER_HEADER};
+ private final String[] columnNames = {CASE_HEADER, CREATEDTIME_HEADER, COMPLETEDTIME_HEADER, STATUS_ICON_HEADER, OUTPUT_FOLDER_HEADER, METADATA_FILE_HEADER};
private DefaultTableModel caseTableModel;
private Path currentlySelectedCase = null;
-
- public AutoIngestCasePanel() {
- init(null);
- }
-
- @Override
- public void addWindowStateListener(JDialog parent) {
- /*
- * Add a window state listener that starts and stops refreshing of the
- * cases table.
- */
- parent.addWindowListener(new WindowAdapter() {
- @Override
- public void windowClosing(WindowEvent e) {
- stopCasesTableRefreshes();
- }
-
- @Override
- public void windowActivated(WindowEvent e) {
- startCasesTableRefreshes();
- }
-
- @Override
- public void windowClosed(WindowEvent e) {
- stopCasesTableRefreshes();
- }
- });
- }
+ private JDialog parentDialog;
/**
* Constructs a panel that allows a user to open cases created by automated
* ingest.
- *
- * @param parent The parent dialog for this panel.
*/
- public AutoIngestCasePanel(JDialog parent) {
- init(parent);
- }
-
- public void init(JDialog parent) {
+ MultiUserCasesPanel(JDialog parentDialog) {
+ this.parentDialog = parentDialog;
caseTableModel = new DefaultTableModel(columnNames, 0) {
private static final long serialVersionUID = 1L;
@@ -146,6 +103,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
public boolean isCellEditable(int row, int column) {
return false;
}
+
@Override
public Class> getColumnClass(int col) {
if (this.getColumnName(col).equals(CREATEDTIME_HEADER) || this.getColumnName(col).equals(COMPLETEDTIME_HEADER)) {
@@ -184,13 +142,15 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
theColumn.setWidth(TIME_COL_PREFERRED_WIDTH);
theColumn = casesTable.getColumn(STATUS_ICON_HEADER);
- theColumn.setCellRenderer(new CaseStatusIconCellRenderer());
+ theColumn.setCellRenderer(new StatusIconCellRenderer());
theColumn.setMinWidth(STATUS_COL_MIN_WIDTH);
theColumn.setMaxWidth(STATUS_COL_MAX_WIDTH);
theColumn.setPreferredWidth(STATUS_COL_PREFERRED_WIDTH);
theColumn.setWidth(STATUS_COL_PREFERRED_WIDTH);
casesTable.removeColumn(casesTable.getColumn(OUTPUT_FOLDER_HEADER));
+ casesTable.removeColumn(casesTable.getColumn(METADATA_FILE_HEADER));
+ casesTable.setRowSorter(new RowSorter<>(caseTableModel));
/*
* Listen for row selection changes and set button state for the current
@@ -203,75 +163,39 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
}
setButtons();
});
-
- /*
- * Add a window state listener that starts and stops refreshing of the
- * cases table.
- */
- if (parent != null) {
- parent.addWindowListener(new WindowAdapter() {
- @Override
- public void windowClosing(WindowEvent e) {
- stopCasesTableRefreshes();
- }
-
- @Override
- public void windowActivated(WindowEvent e) {
- startCasesTableRefreshes();
- }
-
- @Override
- public void windowClosed(WindowEvent e) {
- stopCasesTableRefreshes();
- }
- });
- }
- }
-
- /**
- * Start doing periodic refreshes of the cases table.
- */
- private void startCasesTableRefreshes() {
- if (null == casesTableRefreshExecutor) {
- casesTableRefreshExecutor = new ScheduledThreadPoolExecutor(1);
- this.casesTableRefreshExecutor.scheduleAtFixedRate(() -> {
- refreshCasesTable();
- }, MILLIS_TO_WAIT_BEFORE_STARTING, MILLIS_TO_WAIT_BETWEEN_UPDATES, TimeUnit.MILLISECONDS);
- }
- }
-
- /**
- * Stop doing periodic refreshes of the cases table.
- */
- private void stopCasesTableRefreshes() {
- if (null != casesTableRefreshExecutor) {
- casesTableRefreshExecutor.shutdown();
- }
- this.casesTableRefreshExecutor = null;
- }
-
- /*
- * Updates the view presented by the panel.
- */
- public void updateView() {
- Thread thread = new Thread(() -> {
- refreshCasesTable();
- });
- thread.start();
}
/**
* Gets the list of cases known to the review mode cases manager and
* refreshes the cases table.
*/
- private void refreshCasesTable() {
+ void refresh() {
+ setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+
try {
currentlySelectedCase = getSelectedCase();
- AutoIngestCaseManager manager = AutoIngestCaseManager.getInstance();
- List theModel = manager.getCases();
- EventQueue.invokeLater(new CaseTableRefreshTask(theModel));
- } catch (Exception ex) {
- logger.log(Level.SEVERE, "Unexpected exception in refreshCasesTable", ex); //NON-NLS
+ MultiUserCaseManager manager = MultiUserCaseManager.getInstance();
+ List cases = manager.getCases();
+ cases.sort(REVERSE_DATE_MODIFIED_COMPARATOR);
+ caseTableModel.setRowCount(0);
+ long now = new Date().getTime();
+ for (MultiUserCase autoIngestCase : cases) {
+ if (passesTimeFilter(now, autoIngestCase.getLastAccessedDate().getTime())) {
+ caseTableModel.addRow(new Object[]{
+ autoIngestCase.getCaseDisplayName(),
+ autoIngestCase.getCreationDate(),
+ autoIngestCase.getLastAccessedDate(),
+ (MultiUserCaseManager.CaseStatus.OK != autoIngestCase.getStatus()) ? StatusIconCellRenderer.Status.WARNING : StatusIconCellRenderer.Status.OK,
+ autoIngestCase.getCaseDirectoryPath().toString(),
+ autoIngestCase.getMetadataFileName()});
+ }
+ }
+ setSelectedCase(currentlySelectedCase);
+ setButtons();
+ } catch (MultiUserCaseManager.MultiUserCaseManagerException | CoordinationService.CoordinationServiceException ex) {
+ LOGGER.log(Level.SEVERE, "Unexpected exception while refreshing the table.", ex); //NON-NLS
+ } finally {
+ setCursor(null);
}
}
@@ -320,103 +244,108 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
* in the cases table.
*/
private void setButtons() {
- boolean enabled = casesTable.getSelectedRow() >= 0 && casesTable.getSelectedRow() < casesTable.getRowCount();
- bnOpen.setEnabled(enabled);
- bnShowLog.setEnabled(enabled);
+ boolean openEnabled = casesTable.getSelectedRow() >= 0 && casesTable.getSelectedRow() < casesTable.getRowCount();
+ bnOpen.setEnabled(openEnabled);
+
+ Path pathToLog = getSelectedCaseLogFilePath();
+ boolean showLogEnabled = openEnabled && pathToLog != null && pathToLog.toFile().exists();
+ bnShowLog.setEnabled(showLogEnabled);
}
/**
- * Opens a case.
+ * Retrieves the log file path for the selected case in the cases table.
+ *
+ * @return The case log path.
+ */
+ private Path getSelectedCaseLogFilePath() {
+ Path retValue = null;
+
+ int selectedRow = casesTable.getSelectedRow();
+ int rowCount = casesTable.getRowCount();
+ if (selectedRow >= 0 && selectedRow < rowCount) {
+ String caseDirectory = (String) caseTableModel.getValueAt(casesTable.convertRowIndexToModel(selectedRow), COLUMN_HEADERS.OUTPUTFOLDER.ordinal());
+ retValue = Paths.get(caseDirectory, LOG_FILE_NAME);
+ }
+
+ return retValue;
+ }
+
+ /**
+ * Open a case.
*
* @param caseMetadataFilePath The path to the case metadata file.
*/
private void openCase(Path caseMetadataFilePath) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
- new SwingWorker() {
-
- @Override
- protected Void doInBackground() throws Exception {
- AutoIngestCaseManager.getInstance().openCase(caseMetadataFilePath);
- stopCasesTableRefreshes();
- StartupWindowProvider.getInstance().close();
- CueBannerPanel.closeAutoIngestCasesWindow();
- return null;
+ try {
+ StartupWindowProvider.getInstance().close();
+ if (parentDialog != null) {
+ parentDialog.setVisible(false);
}
-
- @Override
- protected void done() {
- try {
- get();
- } catch (InterruptedException | ExecutionException ex) {
- if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) {
- logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS
- MessageNotifyUtil.Message.error(ex.getCause().getLocalizedMessage());
- }
- StartupWindowProvider.getInstance().open();
- } finally {
- setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
- }
+ MultiUserCaseManager.getInstance().openCase(caseMetadataFilePath);
+ } catch (CaseActionException | MultiUserCaseManager.MultiUserCaseManagerException ex) {
+ if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) {
+ LOGGER.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS
+ MessageNotifyUtil.Message.error(ex.getCause().getLocalizedMessage());
}
- }.execute();
+ StartupWindowProvider.getInstance().open();
+ } finally {
+ setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+ }
}
/**
- * A task that refreshes the cases table using a list of auto ingest cases.
+ * Indicates whether or not a time satisfies a time filter defined by this
+ * panel's time filter radio buttons.
+ *
+ * @param currentTime The current date and time in milliseconds from the
+ * Unix epoch.
+ * @param inputTime The date and time to be tested as milliseconds from
+ * the Unix epoch.
*/
- private class CaseTableRefreshTask implements Runnable {
+ private boolean passesTimeFilter(long currentTime, long inputTime) {
+ long numberOfUnits = 10;
+ long multiplier = 1;
+ if (rbAllCases.isSelected()) {
+ return true;
+ } else if (rbMonths.isSelected()) {
+ multiplier = 31;
+ } else if (rbWeeks.isSelected()) {
+ multiplier = 7;
+ } else if (rbDays.isSelected()) {
+ multiplier = 1;
+ }
+ return ((currentTime - inputTime) / (1000 * 60 * 60 * 24)) < (numberOfUnits * multiplier);
+ }
- private final List cases;
+ /**
+ * RowSorter which makes columns whose type is Date to be sorted first in
+ * Descending order then in Ascending order
+ */
+ private static class RowSorter extends TableRowSorter {
- CaseTableRefreshTask(List cases) {
- setButtons();
- this.cases = cases;
+ RowSorter(M tModel) {
+ super(tModel);
}
- /**
- * @inheritDoc
- */
@Override
- public void run() {
- cases.sort(reverseDateModifiedComparator);
- caseTableModel.setRowCount(0);
- long now = new Date().getTime();
- for (AutoIngestCase autoIngestCase : cases) {
- if (passesTimeFilter(now, autoIngestCase.getLastAccessedDate().getTime())) {
- caseTableModel.addRow(new Object[]{
- autoIngestCase.getCaseName(),
- autoIngestCase.getCreationDate(),
- autoIngestCase.getLastAccessedDate(),
- (AutoIngestCase.CaseStatus.OK != autoIngestCase.getStatus()),
- autoIngestCase.getCaseDirectoryPath().toString()});
+ public void toggleSortOrder(int column) {
+ if (!this.getModel().getColumnClass(column).equals(Date.class)) {
+ super.toggleSortOrder(column); //if it isn't a date column perform the regular sorting
+ } else {
+ ArrayList sortKeys = new ArrayList<>(getSortKeys());
+ if (sortKeys.isEmpty() || sortKeys.get(0).getColumn() != column) { //sort descending
+ sortKeys.add(0, new RowSorter.SortKey(column, SortOrder.DESCENDING));
+ } else if (sortKeys.get(0).getSortOrder() == SortOrder.ASCENDING) {
+ sortKeys.removeIf(key -> key.getColumn() == column);
+ sortKeys.add(0, new RowSorter.SortKey(column, SortOrder.DESCENDING));
+ } else {
+ sortKeys.removeIf(key -> key.getColumn() == column);
+ sortKeys.add(0, new RowSorter.SortKey(column, SortOrder.ASCENDING));
}
+ setSortKeys(sortKeys);
}
- setSelectedCase(currentlySelectedCase);
}
-
- /**
- * Indicates whether or not a time satisfies a time filter defined by
- * this panel's time filter radio buttons.
- *
- * @param currentTime The current date and time in milliseconds from the
- * Unix epoch.
- * @param inputTime The date and time to be tested as milliseconds
- * from the Unix epoch.
- */
- private boolean passesTimeFilter(long currentTime, long inputTime) {
- long numberOfUnits = 10;
- long multiplier = 1;
- if (rbAllCases.isSelected()) {
- return true;
- } else if (rbMonths.isSelected()) {
- multiplier = 31;
- } else if (rbWeeks.isSelected()) {
- multiplier = 7;
- } else if (rbDays.isSelected()) {
- multiplier = 1;
- }
- return ((currentTime - inputTime) / (1000 * 60 * 60 * 24)) < (numberOfUnits * multiplier);
- }
-
}
/**
@@ -443,7 +372,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
setName("Completed Cases"); // NOI18N
- org.openide.awt.Mnemonics.setLocalizedText(bnOpen, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.bnOpen.text")); // NOI18N
+ org.openide.awt.Mnemonics.setLocalizedText(bnOpen, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.bnOpen.text")); // NOI18N
bnOpen.setEnabled(false);
bnOpen.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
@@ -451,9 +380,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
}
});
- casesTable.setAutoCreateRowSorter(true);
casesTable.setModel(caseTableModel);
- casesTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
casesTable.setRowHeight(20);
casesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
casesTable.addMouseListener(new java.awt.event.MouseAdapter() {
@@ -463,7 +390,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
});
scrollPaneTable.setViewportView(casesTable);
- org.openide.awt.Mnemonics.setLocalizedText(bnRefresh, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.bnRefresh.text")); // NOI18N
+ org.openide.awt.Mnemonics.setLocalizedText(bnRefresh, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.bnRefresh.text")); // NOI18N
bnRefresh.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnRefreshActionPerformed(evt);
@@ -472,7 +399,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
rbGroupHistoryLength.add(rbAllCases);
rbAllCases.setSelected(true);
- org.openide.awt.Mnemonics.setLocalizedText(rbAllCases, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbAllCases.text")); // NOI18N
+ org.openide.awt.Mnemonics.setLocalizedText(rbAllCases, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.rbAllCases.text")); // NOI18N
rbAllCases.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
rbAllCasesItemStateChanged(evt);
@@ -494,8 +421,8 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
.addComponent(rbAllCases))
);
- org.openide.awt.Mnemonics.setLocalizedText(bnShowLog, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.bnShowLog.text")); // NOI18N
- bnShowLog.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.bnShowLog.toolTipText")); // NOI18N
+ org.openide.awt.Mnemonics.setLocalizedText(bnShowLog, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.bnShowLog.text")); // NOI18N
+ bnShowLog.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.bnShowLog.toolTipText")); // NOI18N
bnShowLog.setEnabled(false);
bnShowLog.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
@@ -504,7 +431,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
});
rbGroupHistoryLength.add(rbDays);
- org.openide.awt.Mnemonics.setLocalizedText(rbDays, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbDays.text")); // NOI18N
+ org.openide.awt.Mnemonics.setLocalizedText(rbDays, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.rbDays.text")); // NOI18N
rbDays.setName(""); // NOI18N
rbDays.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
@@ -513,7 +440,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
});
rbGroupHistoryLength.add(rbWeeks);
- org.openide.awt.Mnemonics.setLocalizedText(rbWeeks, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbWeeks.text")); // NOI18N
+ org.openide.awt.Mnemonics.setLocalizedText(rbWeeks, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.rbWeeks.text")); // NOI18N
rbWeeks.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
rbWeeksItemStateChanged(evt);
@@ -521,7 +448,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
});
rbGroupHistoryLength.add(rbMonths);
- org.openide.awt.Mnemonics.setLocalizedText(rbMonths, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbMonths.text")); // NOI18N
+ org.openide.awt.Mnemonics.setLocalizedText(rbMonths, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.rbMonths.text")); // NOI18N
rbMonths.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
rbMonthsItemStateChanged(evt);
@@ -529,7 +456,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
});
rbGroupLabel.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
- org.openide.awt.Mnemonics.setLocalizedText(rbGroupLabel, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbGroupLabel.text")); // NOI18N
+ org.openide.awt.Mnemonics.setLocalizedText(rbGroupLabel, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.rbGroupLabel.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
@@ -556,7 +483,7 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(bnRefresh)
.addGap(4, 4, 4))
- .addComponent(scrollPaneTable, javax.swing.GroupLayout.DEFAULT_SIZE, 1007, Short.MAX_VALUE))
+ .addComponent(scrollPaneTable))
.addContainerGap())
);
layout.setVerticalGroup(
@@ -588,10 +515,12 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
*/
private void bnOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOpenActionPerformed
int modelRow = casesTable.convertRowIndexToModel(casesTable.getSelectedRow());
- Path caseMetadataFilePath = Paths.get((String) caseTableModel.getValueAt(modelRow,
- COLUMN_HEADERS.OUTPUTFOLDER.ordinal()),
- caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.CASE.ordinal()) + CaseMetadata.getFileExtension());
- openCase(caseMetadataFilePath);
+ String caseDirectory = (String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.OUTPUTFOLDER.ordinal());
+ Path caseMetadataFilePath = Paths.get(caseDirectory, (String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.METADATA_FILE.ordinal()));
+
+ new Thread(() -> {
+ openCase(caseMetadataFilePath);
+ }).start();
}//GEN-LAST:event_bnOpenActionPerformed
/**
@@ -599,53 +528,50 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
*
* @param evt -- The event that caused this to be called
*/
- private void bnRefreshActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bnRefreshActionPerformed
- {//GEN-HEADEREND:event_bnRefreshActionPerformed
- updateView();
- }//GEN-LAST:event_bnRefreshActionPerformed
+ private void bnRefreshActionPerformed(java.awt.event.ActionEvent evt) {
+ refresh();
+ }
- private void rbDaysItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbDaysItemStateChanged
+ private void rbDaysItemStateChanged(java.awt.event.ItemEvent evt) {
if (rbDays.isSelected()) {
- updateView();
+ refresh();
}
- }//GEN-LAST:event_rbDaysItemStateChanged
+ }
private void rbAllCasesItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbAllCasesItemStateChanged
if (rbAllCases.isSelected()) {
- updateView();
+ refresh();
}
}//GEN-LAST:event_rbAllCasesItemStateChanged
private void rbMonthsItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbMonthsItemStateChanged
if (rbMonths.isSelected()) {
- updateView();
+ refresh();
}
}//GEN-LAST:event_rbMonthsItemStateChanged
private void rbWeeksItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbWeeksItemStateChanged
if (rbWeeks.isSelected()) {
- updateView();
+ refresh();
}
}//GEN-LAST:event_rbWeeksItemStateChanged
private void bnShowLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnShowLogActionPerformed
- int selectedRow = casesTable.convertRowIndexToModel(casesTable.getSelectedRow());
- int rowCount = casesTable.getRowCount();
- if (selectedRow >= 0 && selectedRow < rowCount) {
- String thePath = (String) caseTableModel.getValueAt(selectedRow, COLUMN_HEADERS.OUTPUTFOLDER.ordinal());
- Path pathToLog = AutoIngestJobLogger.getLogPath(Paths.get(thePath));
+ Path pathToLog = getSelectedCaseLogFilePath();
+ if (pathToLog != null) {
try {
if (pathToLog.toFile().exists()) {
Desktop.getDesktop().edit(pathToLog.toFile());
+
} else {
- JOptionPane.showMessageDialog(this, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "DisplayLogDialog.cannotFindLog"),
- org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "DisplayLogDialog.unableToShowLogFile"), JOptionPane.ERROR_MESSAGE);
+ JOptionPane.showMessageDialog(this, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.cannotFindLog"),
+ org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.unableToShowLogFile"), JOptionPane.ERROR_MESSAGE);
}
} catch (IOException ex) {
- logger.log(Level.SEVERE, String.format("Error attempting to open case auto ingest log file %s", pathToLog), ex);
+ LOGGER.log(Level.SEVERE, String.format("Error attempting to open case auto ingest log file %s", pathToLog), ex);
JOptionPane.showMessageDialog(this,
- org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "DisplayLogDialog.cannotOpenLog"),
- org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "DisplayLogDialog.unableToShowLogFile"),
+ org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.cannotOpenLog"),
+ org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.unableToShowLogFile"),
JOptionPane.PLAIN_MESSAGE);
}
}
@@ -654,9 +580,8 @@ public final class AutoIngestCasePanel extends JPanel implements AutoIngestCaseP
private void casesTableMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_casesTableMouseClicked
if (evt.getClickCount() == 2) {
int modelRow = casesTable.convertRowIndexToModel(casesTable.getSelectedRow());
- Path caseMetadataFilePath = Paths.get((String) caseTableModel.getValueAt(modelRow,
- COLUMN_HEADERS.OUTPUTFOLDER.ordinal()),
- caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.CASE.ordinal()) + CaseMetadata.getFileExtension());
+ String caseDirectory = (String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.OUTPUTFOLDER.ordinal());
+ Path caseMetadataFilePath = Paths.get(caseDirectory, (String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.METADATA_FILE.ordinal()));
openCase(caseMetadataFilePath);
}
}//GEN-LAST:event_casesTableMouseClicked
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java
index fad0196288..7c7d22066e 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;
@@ -1251,13 +1250,13 @@ public abstract class AbstractSqlEamDb implements EamDb {
}
/**
- * Remove a reference set and all hashes contained in it.
+ * Remove a reference set and all entries contained in it.
* @param referenceSetID
* @throws EamDbException
*/
@Override
public void deleteReferenceSet(int referenceSetID) throws EamDbException{
- deleteReferenceSetFiles(referenceSetID);
+ deleteReferenceSetEntries(referenceSetID);
deleteReferenceSetEntry(referenceSetID);
}
@@ -1277,7 +1276,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
preparedStatement.setInt(1, referenceSetID);
preparedStatement.executeUpdate();
} catch (SQLException ex) {
- throw new EamDbException("Error deleting reference set", ex); // NON-NLS
+ throw new EamDbException("Error deleting reference set " + referenceSetID, ex); // NON-NLS
} finally {
EamDbUtil.closePreparedStatement(preparedStatement);
EamDbUtil.closeConnection(conn);
@@ -1285,16 +1284,18 @@ public abstract class AbstractSqlEamDb implements EamDb {
}
/**
- * Remove all entries for this reference set from the reference_file table
+ * Remove all entries for this reference set from the reference tables
+ * (Currently only removes entries from the reference_file table)
* @param referenceSetID
* @throws EamDbException
*/
- private void deleteReferenceSetFiles(int referenceSetID) throws EamDbException{
+ private void deleteReferenceSetEntries(int referenceSetID) throws EamDbException{
Connection conn = connect();
PreparedStatement preparedStatement = null;
String sql = "DELETE FROM %s WHERE reference_set_id=?";
+ // When other reference types are added, this will need to loop over all the tables
String fileTableName = EamDbUtil.correlationTypeToReferenceTableName(getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID));
try {
@@ -1302,7 +1303,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
preparedStatement.setInt(1, referenceSetID);
preparedStatement.executeUpdate();
} catch (SQLException ex) {
- throw new EamDbException("Error deleting files from reference set", ex); // NON-NLS
+ throw new EamDbException("Error deleting files from reference set " + referenceSetID, ex); // NON-NLS
} finally {
EamDbUtil.closePreparedStatement(preparedStatement);
EamDbUtil.closeConnection(conn);
@@ -1310,31 +1311,46 @@ public abstract class AbstractSqlEamDb implements EamDb {
}
/**
- * Check whether the given reference set exists in the central repository.
+ * Check whether a reference set with the given parameters exists in the central repository.
+ * Used to check whether reference sets saved in the settings are still present.
* @param referenceSetID
- * @param hashSetName
+ * @param setName
* @param version
* @return true if a matching entry exists in the central repository
* @throws EamDbException
*/
@Override
- public boolean referenceSetIsValid(int referenceSetID, String hashSetName, String version) throws EamDbException{
+ public boolean referenceSetIsValid(int referenceSetID, String setName, String version) throws EamDbException{
EamGlobalSet refSet = this.getReferenceSetByID(referenceSetID);
if(refSet == null){
return false;
}
- return(refSet.getSetName().equals(hashSetName) && refSet.getVersion().equals(version));
+ return(refSet.getSetName().equals(setName) && refSet.getVersion().equals(version));
}
-
+
/**
- * Check if the given hash is in a specific reference set
+ * Check if the given file hash is in this reference set.
+ * Only searches the reference_files table.
* @param hash
* @param referenceSetID
* @return true if the hash is found in the reference set
+ * @throws EamDbException
*/
@Override
- public boolean isHashInReferenceSet(String hash, int referenceSetID) throws EamDbException{
+ public boolean isFileHashInReferenceSet(String hash, int referenceSetID) throws EamDbException{
+ return isValueInReferenceSet(hash, referenceSetID, CorrelationAttribute.FILES_TYPE_ID);
+ }
+
+ /**
+ * Check if the given value is in a specific reference set
+ * @param value
+ * @param referenceSetID
+ * @param correlationTypeID
+ * @return true if the value is found in the reference set
+ */
+ @Override
+ public boolean isValueInReferenceSet(String value, int referenceSetID, int correlationTypeID) throws EamDbException{
Connection conn = connect();
@@ -1343,17 +1359,17 @@ public abstract class AbstractSqlEamDb implements EamDb {
ResultSet resultSet = null;
String sql = "SELECT count(*) FROM %s WHERE value=? AND reference_set_id=?";
- String fileTableName = EamDbUtil.correlationTypeToReferenceTableName(getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID));
+ String fileTableName = EamDbUtil.correlationTypeToReferenceTableName(getCorrelationTypeById(correlationTypeID));
try {
preparedStatement = conn.prepareStatement(String.format(sql, fileTableName));
- preparedStatement.setString(1, hash);
+ preparedStatement.setString(1, value);
preparedStatement.setInt(2, referenceSetID);
resultSet = preparedStatement.executeQuery();
resultSet.next();
matchingInstances = resultSet.getLong(1);
} catch (SQLException ex) {
- throw new EamDbException("Error determining if file is in reference set.", ex); // NON-NLS
+ throw new EamDbException("Error determining if value (" + value + ") is in reference set " + referenceSetID, ex); // NON-NLS
} finally {
EamDbUtil.closePreparedStatement(preparedStatement);
EamDbUtil.closeResultSet(resultSet);
@@ -1372,7 +1388,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
* @return Global known status of the artifact
*/
@Override
- public boolean isArtifactlKnownBadByReference(CorrelationAttribute.Type aType, String value) throws EamDbException {
+ public boolean isArtifactKnownBadByReference(CorrelationAttribute.Type aType, String value) throws EamDbException {
// TEMP: Only support file correlation type
if (aType.getId() != CorrelationAttribute.FILES_TYPE_ID) {
@@ -1521,30 +1537,6 @@ public abstract class AbstractSqlEamDb implements EamDb {
EamGlobalSet globalSet = getReferenceSetByID(referenceSetID);
return (getOrganizationByID(globalSet.getOrgID()));
}
-
- /**
- * Add a new reference set
- *
- * @param orgID
- * @param setName
- * @param version
- * @param importDate
- * @return the reference set ID of the newly created set
- * @throws EamDbException
- */
- @Override
- public int newReferenceSet(int orgID, String setName, String version, TskData.FileKnown knownStatus,
- boolean isReadOnly) throws EamDbException {
- EamDb dbManager = EamDb.getInstance();
- EamGlobalSet eamGlobalSet = new EamGlobalSet(
- orgID,
- setName,
- version,
- knownStatus,
- isReadOnly,
- LocalDate.now());
- return dbManager.newReferencelSet(eamGlobalSet);
- }
/**
* Update an existing organization.
@@ -1618,7 +1610,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
* @throws EamDbException
*/
@Override
- public int newReferencelSet(EamGlobalSet eamGlobalSet) throws EamDbException {
+ public int newReferenceSet(EamGlobalSet eamGlobalSet) throws EamDbException {
Connection conn = connect();
PreparedStatement preparedStatement1 = null;
@@ -1757,14 +1749,15 @@ public abstract class AbstractSqlEamDb implements EamDb {
}
/**
- * Check whether a reference set with the given name/version is in the central repo
- * @param hashSetName
+ * Check whether a reference set with the given name/version is in the central repo.
+ * Used to check for name collisions when creating reference sets.
+ * @param referenceSetName
* @param version
* @return true if a matching set is found
* @throws EamDbException
*/
@Override
- public boolean referenceSetExists(String hashSetName, String version) throws EamDbException{
+ public boolean referenceSetExists(String referenceSetName, String version) throws EamDbException{
Connection conn = connect();
PreparedStatement preparedStatement1 = null;
@@ -1773,13 +1766,14 @@ public abstract class AbstractSqlEamDb implements EamDb {
try {
preparedStatement1 = conn.prepareStatement(sql1);
- preparedStatement1.setString(1, hashSetName);
+ preparedStatement1.setString(1, referenceSetName);
preparedStatement1.setString(2, version);
resultSet = preparedStatement1.executeQuery();
return (resultSet.next());
} catch (SQLException ex) {
- throw new EamDbException("Error getting reference instances by type and value.", ex); // NON-NLS
+ throw new EamDbException("Error testing whether reference set exists (name: " + referenceSetName
+ + " version: " + version, ex); // NON-NLS
} finally {
EamDbUtil.closePreparedStatement(preparedStatement1);
EamDbUtil.closeResultSet(resultSet);
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java
index dc0a87ea07..1011f837cc 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java
@@ -362,38 +362,51 @@ 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
*/
public void deleteReferenceSet(int referenceSetID) throws EamDbException;
/**
- * Check whether the given reference set exists in the central repository.
+ * Check whether a reference set with the given parameters exists in the central repository.
+ * Used to check whether reference sets saved in the settings are still present.
* @param referenceSetID
- * @param hashSetName
+ * @param referenceSetName
* @param version
* @return true if a matching entry exists in the central repository
* @throws EamDbException
*/
- public boolean referenceSetIsValid(int referenceSetID, String hashSetName, String version) throws EamDbException;
+ public boolean referenceSetIsValid(int referenceSetID, String referenceSetName, String version) throws EamDbException;
/**
- * Check whether a reference set with the given name/version is in the central repo
- * @param hashSetName
+ * Check whether a reference set with the given name/version is in the central repo.
+ * Used to check for name collisions when creating reference sets.
+ * @param referenceSetName
* @param version
* @return true if a matching set is found
* @throws EamDbException
*/
- public boolean referenceSetExists(String hashSetName, String version) throws EamDbException;
+ public boolean referenceSetExists(String referenceSetName, String version) throws EamDbException;
/**
- * Check if the given hash is in a specific reference set
+ * Check if the given file hash is in this reference set.
+ * Only searches the reference_files table.
* @param hash
* @param referenceSetID
* @return true if the hash is found in the reference set
+ * @throws EamDbException
*/
- public boolean isHashInReferenceSet(String hash, int referenceSetID) throws EamDbException;
+ public boolean isFileHashInReferenceSet(String hash, int referenceSetID) throws EamDbException;
+
+ /**
+ * Check if the given value is in a specific reference set
+ * @param value
+ * @param referenceSetID
+ * @param correlationTypeID
+ * @return true if the hash is found in the reference set
+ */
+ public boolean isValueInReferenceSet(String value, int referenceSetID, int correlationTypeID) throws EamDbException;
/**
* Is the artifact known as bad according to the reference entries?
@@ -403,7 +416,7 @@ public interface EamDb {
*
* @return Global known status of the artifact
*/
- boolean isArtifactlKnownBadByReference(CorrelationAttribute.Type aType, String value) throws EamDbException;
+ boolean isArtifactKnownBadByReference(CorrelationAttribute.Type aType, String value) throws EamDbException;
/**
* Add a new organization
@@ -472,20 +485,7 @@ public interface EamDb {
*
* @throws EamDbException
*/
- int newReferencelSet(EamGlobalSet eamGlobalSet) throws EamDbException;
-
- /**
- * Add a new reference set
- *
- * @param orgID
- * @param setName
- * @param version
- * @param importDate
- * @return the reference set ID of the newly created set
- * @throws EamDbException
- */
- int newReferenceSet(int orgID, String setName, String version, TskData.FileKnown knownStatus,
- boolean isReadOnly) throws EamDbException;
+ int newReferenceSet(EamGlobalSet eamGlobalSet) throws EamDbException;
/**
* Get a global set by ID
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 45a0388561..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
*/
@@ -657,27 +657,28 @@ public class SqliteEamDb extends AbstractSqlEamDb {
* @return true if the hash is found in the reference set
*/
@Override
- public boolean isHashInReferenceSet(String hash, int referenceSetID) throws EamDbException{
+ public boolean isValueInReferenceSet(String value, int referenceSetID, int correlationTypeID) throws EamDbException {
try{
acquireSharedLock();
- return super.isHashInReferenceSet(hash, referenceSetID);
+ return super.isValueInReferenceSet(value, referenceSetID, correlationTypeID);
} finally {
releaseSharedLock();
}
}
/**
- * Check whether a reference set with the given name/version is in the central repo
- * @param hashSetName
+ * Check whether a reference set with the given name/version is in the central repo.
+ * Used to check for name collisions when creating reference sets.
+ * @param referenceSetName
* @param version
* @return true if a matching set is found
* @throws EamDbException
*/
@Override
- public boolean referenceSetExists(String hashSetName, String version) throws EamDbException {
+ public boolean referenceSetExists(String referenceSetName, String version) throws EamDbException {
try{
acquireSharedLock();
- return super.referenceSetExists(hashSetName, version);
+ return super.referenceSetExists(referenceSetName, version);
} finally {
releaseSharedLock();
}
@@ -692,10 +693,10 @@ public class SqliteEamDb extends AbstractSqlEamDb {
* @return Global known status of the artifact
*/
@Override
- public boolean isArtifactlKnownBadByReference(CorrelationAttribute.Type aType, String value) throws EamDbException {
+ public boolean isArtifactKnownBadByReference(CorrelationAttribute.Type aType, String value) throws EamDbException {
try{
acquireSharedLock();
- return super.isArtifactlKnownBadByReference(aType, value);
+ return super.isArtifactKnownBadByReference(aType, value);
} finally {
releaseSharedLock();
}
@@ -785,10 +786,10 @@ public class SqliteEamDb extends AbstractSqlEamDb {
* @throws EamDbException
*/
@Override
- public int newReferencelSet(EamGlobalSet eamGlobalSet) throws EamDbException {
+ public int newReferenceSet(EamGlobalSet eamGlobalSet) throws EamDbException {
try{
acquireExclusiveLock();
- return super.newReferencelSet(eamGlobalSet);
+ return super.newReferenceSet(eamGlobalSet);
} finally {
releaseExclusiveLock();
}
diff --git a/Core/src/org/sleuthkit/autopsy/coordinationservice/CaseNodeData.java b/Core/src/org/sleuthkit/autopsy/coordinationservice/CaseNodeData.java
new file mode 100755
index 0000000000..0b220e04b2
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/coordinationservice/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.coordinationservice;
+
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+
+/**
+ * An object that converts case data for a case directory coordination service
+ * node to and from byte arrays.
+ */
+public final class CaseNodeData {
+
+ private static final int CURRENT_VERSION = 0;
+
+ private int version;
+ private boolean errorsOccurred;
+
+ /**
+ * Gets the current version of the case directory coordination service node
+ * data.
+ *
+ * @return The version number.
+ */
+ public static int getCurrentVersion() {
+ return CaseNodeData.CURRENT_VERSION;
+ }
+
+ /**
+ * Uses coordination service node data to construct an object that converts
+ * case data for a case directory coordination service node to and from byte
+ * arrays.
+ *
+ * @param nodeData The raw bytes received from the coordination service.
+ *
+ * @throws InvalidDataException If the node data buffer is smaller than
+ * expected.
+ */
+ public CaseNodeData(byte[] nodeData) throws InvalidDataException {
+ if(nodeData == null || nodeData.length == 0) {
+ this.version = CURRENT_VERSION;
+ this.errorsOccurred = false;
+ } else {
+ /*
+ * Get fields from node data.
+ */
+ ByteBuffer buffer = ByteBuffer.wrap(nodeData);
+ try {
+ if (buffer.hasRemaining()) {
+ this.version = buffer.getInt();
+
+ /*
+ * Flags bit format: 76543210
+ * 0-6 --> reserved for future use
+ * 7 --> errorsOccurred
+ */
+ byte flags = buffer.get();
+ this.errorsOccurred = (flags < 0);
+ }
+ } catch (BufferUnderflowException ex) {
+ throw new InvalidDataException("Node data is incomplete", ex);
+ }
+ }
+ }
+
+ /**
+ * Gets whether or not any errors occurred during the processing of the job.
+ *
+ * @return True or false.
+ */
+ public boolean getErrorsOccurred() {
+ return this.errorsOccurred;
+ }
+
+ /**
+ * Sets whether or not any errors occurred during the processing of job.
+ *
+ * @param errorsOccurred True or false.
+ */
+ public void setErrorsOccurred(boolean errorsOccurred) {
+ this.errorsOccurred = errorsOccurred;
+ }
+
+ /**
+ * Gets the node data version number.
+ *
+ * @return The version number.
+ */
+ public int getVersion() {
+ return this.version;
+ }
+
+ /**
+ * Gets the node data as a byte array that can be sent to the coordination
+ * service.
+ *
+ * @return The node data as a byte array.
+ */
+ public byte[] toArray() {
+ ByteBuffer buffer = ByteBuffer.allocate(5);
+
+ buffer.putInt(this.version);
+ buffer.put((byte)(this.errorsOccurred ? 0x80 : 0));
+
+ // Prepare the array
+ byte[] array = new byte[buffer.position()];
+ buffer.rewind();
+ buffer.get(array, 0, array.length);
+
+ return array;
+ }
+
+ public final static class InvalidDataException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ private InvalidDataException(String message) {
+ super(message);
+ }
+
+ private InvalidDataException(String message, Throwable cause) {
+ super(message, cause);
+ }
+ }
+}
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/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/corecomponentinterfaces/BlackboardResultViewer.java b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/BlackboardResultViewer.java
index c196adae4c..f32d82148e 100755
--- a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/BlackboardResultViewer.java
+++ b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/BlackboardResultViewer.java
@@ -24,7 +24,10 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
/**
* Additional functionality of viewers supporting black board results such as
* the directory tree
+ *
+ *@deprecated No longer used.
*/
+@Deprecated
public interface BlackboardResultViewer {
public static final String FINISHED_DISPLAY_EVT = "FINISHED_DISPLAY_EVT"; //NON-NLS
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/TimeStampUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/TimeStampUtils.java
similarity index 73%
rename from Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/TimeStampUtils.java
rename to Core/src/org/sleuthkit/autopsy/coreutils/TimeStampUtils.java
index fe53871dd5..e14b5c5897 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;
@@ -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/datasourceprocessors/AutoIngestDataSourceProcessor.java b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AutoIngestDataSourceProcessor.java
index 11c0559795..163d164376 100755
--- a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AutoIngestDataSourceProcessor.java
+++ b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AutoIngestDataSourceProcessor.java
@@ -43,9 +43,7 @@ public interface AutoIngestDataSourceProcessor extends DataSourceProcessor {
* or less means the data source is not supported by the
* DataSourceProcessor. Value of 100 indicates high certainty in
* being able to process the data source.
- *
- * @throws
- * org.sleuthkit.autopsy.corecomponentinterfaces.AutomatedIngestDataSourceProcessor.AutomatedIngestDataSourceProcessorException
+ * @throws org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
*/
int canProcess(Path dataSourcePath) throws AutoIngestDataSourceProcessorException;
@@ -65,9 +63,7 @@ public interface AutoIngestDataSourceProcessor extends DataSourceProcessor {
* background task to report progress.
* @param callBack Callback that will be used by the background task
* to return results.
- *
- * @throws
- * org.sleuthkit.autopsy.corecomponentinterfaces.AutomatedIngestDataSourceProcessor.AutomatedIngestDataSourceProcessorException
+ * @throws org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
*/
void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) throws AutoIngestDataSourceProcessorException;
diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties
index aa8f1f3a90..647c6f70d3 100755
--- a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties
+++ b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties
@@ -59,8 +59,6 @@ DirectoryTreeFilterNode.action.collapseAll.text=Collapse All
DirectoryTreeFilterNode.action.openFileSrcByAttr.text=Open File Search by Attributes
DirectoryTreeFilterNode.action.runIngestMods.text=Run Ingest Modules
DirectoryTreeTopComponent.action.viewArtContent.text=View Artifact Content
-DirectoryTreeTopComponent.moduleErr=Module Error
-DirectoryTreeTopComponent.moduleErr.msg=A module caused an error listening to DirectoryTreeTopComponent updates. See log to determine which module. Some data could be incomplete.
DirectoryTreeTopComponent.showRejectedCheckBox.text=Show Rejected Results
ExplorerNodeActionVisitor.action.imgDetails.title=Image Details
ExplorerNodeActionVisitor.action.extUnallocToSingleFiles=Extract Unallocated Space to Single Files
diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle_ja.properties
index 2fb64c5bea..6f208c3300 100755
--- a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle_ja.properties
+++ b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle_ja.properties
@@ -56,8 +56,6 @@ DataResultFilterNode.action.viewInDir.text=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\
DirectoryTreeFilterNode.action.openFileSrcByAttr.text=\u5c5e\u6027\u306b\u3088\u308b\u30d5\u30a1\u30a4\u30eb\u691c\u7d22\u3092\u958b\u304f
DirectoryTreeFilterNode.action.runIngestMods.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u5b9f\u884c
DirectoryTreeTopComponent.action.viewArtContent.text=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30b3\u30f3\u30c6\u30f3\u30c4\u3092\u8868\u793a
-DirectoryTreeTopComponent.moduleErr=\u30e2\u30b8\u30e5\u30fc\u30eb\u30a8\u30e9\u30fc
-DirectoryTreeTopComponent.moduleErr.msg=DirectoryTreeTopComponent\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u78ba\u8a8d\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u8d77\u3053\u3057\u307e\u3057\u305f\u3002\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304b\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u4e0d\u5b8c\u5168\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002
ExplorerNodeActionVisitor.action.imgDetails.title=\u30a4\u30e1\u30fc\u30b8\u8a73\u7d30
ExplorerNodeActionVisitor.action.extUnallocToSingleFiles=\u672a\u5272\u308a\u5f53\u3066\u9818\u57df\u5185\u306e\u30c7\u30fc\u30bf\u3092\u30b7\u30f3\u30b0\u30eb\u30d5\u30a1\u30a4\u30eb\u306b\u62bd\u51fa
ExplorerNodeActionVisitor.action.fileSystemDetails.title=\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u8a73\u7d30
@@ -87,4 +85,4 @@ ExtractUnallocAction.done.notifyMsg.completedExtract.msg=\u30d5\u30a1\u30a4\u30e
ExtractUnallocAction.done.errMsg.title=\u62bd\u51fa\u30a8\u30e9\u30fc
ExtractUnallocAction.done.errMsg.msg=\u672a\u5272\u308a\u5f53\u3066\u9818\u57df\u3092\u62bd\u51fa\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a{0}
DirectoryTreeFilterNode.action.collapseAll.text=\u3059\u3079\u3066\u30b3\u30e9\u30d7\u30b9
-ExtractAction.done.notifyMsg.extractErr=\u4e0b\u8a18\u306e\u30d5\u30a1\u30a4\u30eb\u306e\u62bd\u51fa\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a {0}
\ No newline at end of file
+ExtractAction.done.notifyMsg.extractErr=\u4e0b\u8a18\u306e\u30d5\u30a1\u30a4\u30eb\u306e\u62bd\u51fa\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a {0}
diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java
index 03c265daee..9738f1f4a6 100755
--- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java
+++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java
@@ -27,7 +27,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
-import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -56,13 +55,11 @@ import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.core.RuntimeProperties;
import org.sleuthkit.autopsy.core.UserPreferences;
-import org.sleuthkit.autopsy.corecomponentinterfaces.BlackboardResultViewer;
import org.sleuthkit.autopsy.corecomponentinterfaces.CoreComponentControl;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataExplorer;
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
import org.sleuthkit.autopsy.coreutils.Logger;
-import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.datamodel.ArtifactNodeSelectionInfo;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
import org.sleuthkit.autopsy.datamodel.CreditCards;
@@ -99,7 +96,7 @@ import org.sleuthkit.datamodel.TskCoreException;
@Messages({
"DirectoryTreeTopComponent.resultsView.title=Listing"
})
-public final class DirectoryTreeTopComponent extends TopComponent implements DataExplorer, ExplorerManager.Provider, BlackboardResultViewer {
+public final class DirectoryTreeTopComponent extends TopComponent implements DataExplorer, ExplorerManager.Provider {
private final transient ExplorerManager em = new ExplorerManager();
private static DirectoryTreeTopComponent instance;
@@ -851,7 +848,6 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
return false;
}
- @Override
public void viewArtifact(final BlackboardArtifact art) {
int typeID = art.getArtifactTypeID();
String typeName = art.getArtifactTypeName();
@@ -1064,28 +1060,14 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
// Another thread is needed because we have to wait for dataResult to populate
}
- @Override
public void viewArtifactContent(BlackboardArtifact art) {
new ViewContextAction(
NbBundle.getMessage(this.getClass(), "DirectoryTreeTopComponent.action.viewArtContent.text"),
new BlackboardArtifactNode(art)).actionPerformed(null);
}
- @Override
public void addOnFinishedListener(PropertyChangeListener l) {
DirectoryTreeTopComponent.this.addPropertyChangeListener(l);
}
- void fireViewerComplete() {
-
- try {
- firePropertyChange(BlackboardResultViewer.FINISHED_DISPLAY_EVT, 0, 1);
- } catch (Exception e) {
- LOGGER.log(Level.SEVERE, "DirectoryTreeTopComponent listener threw exception", e); //NON-NLS
- MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "DirectoryTreeTopComponent.moduleErr"),
- NbBundle.getMessage(this.getClass(),
- "DirectoryTreeTopComponent.moduleErr.msg"),
- MessageNotifyUtil.MessageType.ERROR);
- }
- }
}
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 @@
diff --git a/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDbConfigPanel.java b/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDbConfigPanel.java
index 9c1875eeb2..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.HashDatabase;
/**
* Instances of this class are used to configure the report module plug in that
@@ -52,7 +52,7 @@ class AddTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel {
private final Map 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/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..843e9e53fa
--- /dev/null
+++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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 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/qa-functional/src/org/sleuthkit/autopsy/testutils/FunctionalTestDspCallback.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/FunctionalTestDspCallback.java
new file mode 100755
index 0000000000..cfa9f3dc59
--- /dev/null
+++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/FunctionalTestDspCallback.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 FunctionalTestDspCallback 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.
+ */
+ FunctionalTestDspCallback(Object monitor) {
+ this.monitor = monitor;
+ }
+
+ /**
+ * Called by the data source processor when it finishes running in its own
+ * thread.
+ *
+ * @param result The result code for the processing of the data
+ * source.
+ * @param errorMessages Any error messages generated during the
+ * processing of the data source.
+ * @param dataSourceContent The content produced by processing the data
+ * source.
+ */
+ @Override
+ public void done(DataSourceProcessorCallback.DataSourceProcessorResult result, List 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/qa-functional/src/org/sleuthkit/autopsy/testutils/FunctionalTestDspProgressMonitor.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/FunctionalTestDspProgressMonitor.java
new file mode 100755
index 0000000000..03d26eb9b2
--- /dev/null
+++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/FunctionalTestDspProgressMonitor.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 FunctionalTestDspProgressMonitor implements DataSourceProcessorProgressMonitor {
+
+ /**
+ * Switches the progress indicator to indeterminate mode (the total number
+ * of work units to be completed is unknown) or determinate mode (the total
+ * number of work units to be completed is unknown).
+ *
+ * @param indeterminate True for indeterminate mode, false for determinate
+ * mode.
+ */
+ @Override
+ public void setIndeterminate(final boolean indeterminate) {
+ }
+
+ /**
+ * Updates the progress indicator with the number of work units completed so
+ * far when in determinate mode (the total number of work units to be
+ * completed is known).
+ *
+ * @param workUnitsCompleted Number of work units completed so far.
+ */
+ @Override
+ public void setProgress(final int workUnitsCompleted) {
+ }
+
+ /**
+ * Updates the progress indicator with a progress message.
+ *
+ * @param message The progress message.
+ */
+ @Override
+ public void setProgressText(final String message) {
+ }
+
+}
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
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AddArchiveTask.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AddArchiveTask.java
index 3bc76e61fd..ffe121cb7d 100755
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AddArchiveTask.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AddArchiveTask.java
@@ -18,21 +18,34 @@
*/
package org.sleuthkit.autopsy.experimental.autoingest;
+import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
+import java.util.UUID;
import java.util.logging.Level;
+import java.util.stream.Collectors;
+import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
+import org.openide.util.Lookup;
import org.sleuthkit.autopsy.casemodule.Case;
+import org.sleuthkit.autopsy.casemodule.LocalDiskDSProcessor;
+import org.sleuthkit.autopsy.casemodule.LocalFilesDSProcessor;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
+import static org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.coreutils.Logger;
+import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
+import org.sleuthkit.autopsy.coreutils.TimeStampUtils;
import org.sleuthkit.datamodel.Content;
/*
- * A runnable that adds an archive data source as well as data sources
- * contained in the archive to the case database.
+ * A runnable that adds an archive data source as well as data sources contained
+ * in the archive to the case database.
*/
class AddArchiveTask implements Runnable {
@@ -42,6 +55,7 @@ class AddArchiveTask implements Runnable {
private final DataSourceProcessorProgressMonitor progressMonitor;
private final DataSourceProcessorCallback callback;
private boolean criticalErrorOccurred;
+ private final Object archiveDspLock;
private static final String ARCHIVE_EXTRACTOR_MODULE_OUTPUT_DIR = "Archive Extractor";
@@ -49,19 +63,20 @@ class AddArchiveTask implements Runnable {
* Constructs a runnable task that adds an archive as well as data sources
* contained in the archive to the case database.
*
- * @param deviceId An ASCII-printable identifier for the device associated
- * with the data source that is intended to be unique across multiple cases
- * (e.g., a UUID).
- * @param archivePath Path to the archive file.
+ * @param deviceId An ASCII-printable identifier for the device
+ * associated with the data source that is intended
+ * to be unique across multiple cases (e.g., a UUID).
+ * @param archivePath Path to the archive file.
* @param progressMonitor Progress monitor to report progress during
- * processing.
- * @param callback Callback to call when processing is done.
+ * processing.
+ * @param callback Callback to call when processing is done.
*/
AddArchiveTask(String deviceId, String archivePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
this.deviceId = deviceId;
this.archivePath = archivePath;
this.callback = callback;
this.progressMonitor = progressMonitor;
+ this.archiveDspLock = new Object();
}
/**
@@ -69,39 +84,172 @@ class AddArchiveTask implements Runnable {
*/
@Override
public void run() {
+ progressMonitor.setIndeterminate(true);
List errorMessages = new ArrayList<>();
List newDataSources = new ArrayList<>();
DataSourceProcessorCallback.DataSourceProcessorResult result;
if (!ArchiveUtil.isArchive(Paths.get(archivePath))) {
criticalErrorOccurred = true;
logger.log(Level.SEVERE, String.format("Input data source is not a valid datasource: %s", archivePath)); //NON-NLS
- errorMessages.add("Input data source is not a valid datasource: " + archivePath);
+ errorMessages.add("Input data source is not a valid datasource: " + archivePath);
result = DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS;
callback.done(result, errorMessages, newDataSources);
}
+ logger.log(Level.INFO, "Using Archive Extractor DSP to process archive {0} ", archivePath);
+
// extract the archive and pass the extracted folder as input
- Path destinationFolder = Paths.get("");
try {
Case currentCase = Case.getCurrentCase();
- // get file name without full path or extension
- String dataSourceFileNameNoExt = FilenameUtils.getBaseName(archivePath);
-
// create folder to extract archive to
- destinationFolder = Paths.get(currentCase.getModuleDirectory(), ARCHIVE_EXTRACTOR_MODULE_OUTPUT_DIR, dataSourceFileNameNoExt + "_" + TimeStampUtils.createTimeStamp());
- destinationFolder.toFile().mkdirs();
+ Path destinationFolder = createDirectoryForFile(archivePath, currentCase.getModuleDirectory());
+ if (destinationFolder.toString().isEmpty()) {
+ // unable to create directory
+ criticalErrorOccurred = true;
+ errorMessages.add(String.format("Unable to create directory {0} to extract archive {1} ", new Object[]{destinationFolder.toString(), archivePath}));
+ logger.log(Level.SEVERE, String.format("Unable to create directory {0} to extract archive {1} ", new Object[]{destinationFolder.toString(), archivePath}));
+ return;
+ }
- // extract contents of ZIP archive into destination folder
- //ArchiveUtil.unpackArchiveFile(archivePath, destinationFolder.toString());
+ // extract contents of ZIP archive into destination folder
+ progressMonitor.setProgressText(String.format("Extracting archive contents to: %s", destinationFolder.toString()));
+ List extractedFiles = ArchiveUtil.unpackArchiveFile(archivePath, destinationFolder.toString());
+ int numExtractedFilesRemaining = extractedFiles.size();
+
+ // lookup all AutomatedIngestDataSourceProcessors so that we only do it once.
+ // LocalDisk, LocalFiles, and ArchiveDSP are removed from the list.
+ List processorCandidates = getListOfValidDataSourceProcessors();
// do processing
-
+ for (String file : extractedFiles) {
+
+ // we only care about files, skip directories
+ File fileObject = new File(file);
+ if (fileObject.isDirectory()) {
+ numExtractedFilesRemaining--;
+ continue;
+ }
+
+ // identify all "valid" DSPs that can process this file
+ List validDataSourceProcessors = getDataSourceProcessorsForFile(Paths.get(file), errorMessages, processorCandidates);
+ if (validDataSourceProcessors.isEmpty()) {
+ continue;
+ }
+
+ // identified a "valid" data source within the archive
+ progressMonitor.setProgressText(String.format("Adding: %s", file));
+
+ /*
+ * NOTE: we have to move the valid data sources to a separate
+ * folder and then add the data source from that folder. This is
+ * necessary because after all valid data sources have been
+ * identified, we are going to add the remaining extracted
+ * contents of the archive as a single logical file set. Hence,
+ * if we do not move the data sources out of the extracted
+ * contents folder, those data source files will get added twice
+ * and can potentially result in duplicate keyword hits.
+ */
+ Path newFolder = createDirectoryForFile(file, currentCase.getModuleDirectory());
+ if (newFolder.toString().isEmpty()) {
+ // unable to create directory
+ criticalErrorOccurred = true;
+ errorMessages.add(String.format("Unable to create directory {0} to extract content of archive {1} ", new Object[]{newFolder.toString(), archivePath}));
+ logger.log(Level.SEVERE, String.format("Unable to create directory {0} to extract content of archive {1} ", new Object[]{newFolder.toString(), archivePath}));
+ return;
+ }
+
+ // Copy it to a different folder
+ FileUtils.copyFileToDirectory(fileObject, newFolder.toFile());
+ Path newFilePath = Paths.get(newFolder.toString(), FilenameUtils.getName(file));
+
+ // Try each DSP in decreasing order of confidence
+ boolean success = false;
+ for (AutoIngestDataSourceProcessor selectedProcessor : validDataSourceProcessors) {
+
+ logger.log(Level.INFO, "Using {0} to process extracted file {1} ", new Object[]{selectedProcessor.getDataSourceType(), file});
+ synchronized (archiveDspLock) {
+ try {
+ UUID taskId = UUID.randomUUID();
+ currentCase.notifyAddingDataSource(taskId);
+ AutoIngestDataSource internalDataSource = new AutoIngestDataSource(deviceId, newFilePath);
+ DataSourceProcessorCallback internalArchiveDspCallBack = new AddDataSourceCallback(currentCase, internalDataSource, taskId, archiveDspLock);
+ selectedProcessor.process(deviceId, newFilePath, progressMonitor, internalArchiveDspCallBack);
+ archiveDspLock.wait();
+
+ // at this point we got the content object(s) from the current DSP.
+ // check whether the data source was processed successfully
+ if ((internalDataSource.getResultDataSourceProcessorResultCode() == CRITICAL_ERRORS)
+ || internalDataSource.getContent().isEmpty()) {
+ // move onto the the next DSP that can process this data source
+ continue;
+ }
+
+ // if we are here it means the data source was addedd successfully
+ success = true;
+ newDataSources.addAll(internalDataSource.getContent());
+
+ // skip all other DSPs for this data source
+ break;
+ } catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) {
+ // Log that the current DSP failed and set the error flag. We consider it an error
+ // if a DSP fails even if a later one succeeds since we expected to be able to process
+ // the data source which each DSP on the list.
+ criticalErrorOccurred = true;
+ errorMessages.add(ex.getMessage());
+ logger.log(Level.SEVERE, "Exception while processing {0} with data source processor {1}", new Object[]{newFilePath.toString(), selectedProcessor.getDataSourceType()});
+ }
+ }
+ }
+
+ if (success) {
+ // one of the DSPs successfully processed the data source. delete the
+ // copy of the data source in the original extracted archive folder.
+ // otherwise the data source is going to be added again as a logical file.
+ numExtractedFilesRemaining--;
+ FileUtils.deleteQuietly(fileObject);
+ } else {
+ // none of the DSPs were able to process the data source. delete the
+ // copy of the data source in the temporary folder. the data source is
+ // going to be added as a logical file with the rest of the extracted contents.
+ FileUtils.deleteQuietly(newFolder.toFile());
+ }
+ }
+
+ // after all archive contents have been examined (and moved to separate folders if necessary),
+ // add remaining extracted contents as one logical file set
+ if (numExtractedFilesRemaining > 0) {
+ progressMonitor.setProgressText(String.format("Adding: %s", destinationFolder.toString()));
+ logger.log(Level.INFO, "Adding directory {0} as logical file set", destinationFolder.toString());
+ synchronized (archiveDspLock) {
+ UUID taskId = UUID.randomUUID();
+ currentCase.notifyAddingDataSource(taskId);
+ AutoIngestDataSource internalDataSource = new AutoIngestDataSource(deviceId, destinationFolder);
+ DataSourceProcessorCallback internalArchiveDspCallBack = new AddDataSourceCallback(currentCase, internalDataSource, taskId, archiveDspLock);
+
+ // folder where archive was extracted to
+ List pathsList = new ArrayList<>();
+ pathsList.add(destinationFolder.toString());
+
+ // use archive file name as the name of the logical file set
+ String archiveFileName = FilenameUtils.getName(archivePath);
+
+ LocalFilesDSProcessor localFilesDSP = new LocalFilesDSProcessor();
+ localFilesDSP.run(deviceId, archiveFileName, pathsList, progressMonitor, internalArchiveDspCallBack);
+
+ archiveDspLock.wait();
+
+ // at this point we got the content object(s) from the current DSP
+ newDataSources.addAll(internalDataSource.getContent());
+ }
+ }
} catch (Exception ex) {
criticalErrorOccurred = true;
errorMessages.add(ex.getMessage());
logger.log(Level.SEVERE, String.format("Critical error occurred while extracting archive %s", archivePath), ex); //NON-NLS
} finally {
+ logger.log(Level.INFO, "Finished processing of archive {0}", archivePath);
+ progressMonitor.setProgress(100);
if (criticalErrorOccurred) {
result = DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS;
} else if (!errorMessages.isEmpty()) {
@@ -113,10 +261,78 @@ class AddArchiveTask implements Runnable {
}
}
- /*
- * Attempts to cancel adding the archive to the case database.
+ /**
+ * Get a list of data source processors. LocalDisk, LocalFiles, and
+ * ArchiveDSP are removed from the list.
+ *
+ * @return List of data source processors
*/
- public void cancelTask() {
+ private List getListOfValidDataSourceProcessors() {
+ Collection extends AutoIngestDataSourceProcessor> processorCandidates = Lookup.getDefault().lookupAll(AutoIngestDataSourceProcessor.class);
+
+ List validDataSourceProcessors = processorCandidates.stream().collect(Collectors.toList());
+
+ for (Iterator iterator = validDataSourceProcessors.iterator(); iterator.hasNext();) {
+ AutoIngestDataSourceProcessor selectedProcessor = iterator.next();
+
+ // skip local files and local disk DSPs, only looking for "valid" data sources.
+ // also skip nested archive files, those will be ingested as logical files and extracted during ingest
+ if ((selectedProcessor instanceof LocalDiskDSProcessor)
+ || (selectedProcessor instanceof LocalFilesDSProcessor)
+ || (selectedProcessor instanceof ArchiveExtractorDSProcessor)) {
+ iterator.remove();
+ }
+ }
+
+ return validDataSourceProcessors;
+ }
+
+ /**
+ * Get a list of data source processors that can process the data source of
+ * interest. The list is sorted by confidence in decreasing order.
+ *
+ * @param dataSourcePath Full path to the data source
+ * @param errorMessages List for error messages
+ * @param errorMessages List of AutoIngestDataSourceProcessor to try
+ *
+ * @return Ordered list of applicable DSPs
+ */
+ private List getDataSourceProcessorsForFile(Path dataSourcePath, List errorMessages,
+ List processorCandidates) {
+
+ // Get an ordered list of data source processors to try
+ List validDataSourceProcessorsForFile = Collections.emptyList();
+ try {
+ validDataSourceProcessorsForFile = DataSourceProcessorUtility.getOrderedListOfDataSourceProcessors(dataSourcePath, processorCandidates);
+ } catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) {
+ criticalErrorOccurred = true;
+ errorMessages.add(ex.getMessage());
+ logger.log(Level.SEVERE, String.format("Critical error occurred while extracting archive %s", archivePath), ex); //NON-NLS
+ return Collections.emptyList();
+ }
+ return validDataSourceProcessorsForFile;
+ }
+
+ /**
+ * Create a directory in ModuleOutput folder based on input file name. A
+ * time stamp is appended to the directory name.
+ *
+ * @param fileName File name
+ * @param baseDirectory Base directory. Typically the case output directory.
+ *
+ * @return Full path to the new directory
+ */
+ private Path createDirectoryForFile(String fileName, String baseDirectory) {
+ // get file name without full path or extension
+ String fileNameNoExt = FilenameUtils.getBaseName(fileName);
+
+ // create folder to extract archive to
+ Path newFolder = Paths.get(baseDirectory, ARCHIVE_EXTRACTOR_MODULE_OUTPUT_DIR, fileNameNoExt + "_" + TimeStampUtils.createTimeStamp());
+ if (newFolder.toFile().mkdirs() == false) {
+ // unable to create directory
+ return Paths.get("");
+ }
+ return newFolder;
}
}
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AddDataSourceCallback.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AddDataSourceCallback.java
index db19fc2fbc..fc00149249 100755
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AddDataSourceCallback.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AddDataSourceCallback.java
@@ -35,7 +35,7 @@ import org.sleuthkit.datamodel.Content;
class AddDataSourceCallback extends DataSourceProcessorCallback {
private final Case caseForJob;
- private final DataSource dataSourceInfo;
+ private final AutoIngestDataSource dataSourceInfo;
private final UUID taskId;
private final Object lock;
@@ -48,7 +48,7 @@ class AddDataSourceCallback extends DataSourceProcessorCallback {
* @param dataSourceInfo The data source
* @param taskId The task id to associate with ingest job events.
*/
- AddDataSourceCallback(Case caseForJob, DataSource dataSourceInfo, UUID taskId, Object lock) {
+ AddDataSourceCallback(Case caseForJob, AutoIngestDataSource dataSourceInfo, UUID taskId, Object lock) {
this.caseForJob = caseForJob;
this.dataSourceInfo = dataSourceInfo;
this.taskId = taskId;
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ArchiveExtractorDSProcessor.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ArchiveExtractorDSProcessor.java
index a649b0f37a..0eba2b8f95 100755
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ArchiveExtractorDSProcessor.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ArchiveExtractorDSProcessor.java
@@ -18,13 +18,15 @@
*/
package org.sleuthkit.autopsy.experimental.autoingest;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.nio.file.Path;
import java.util.UUID;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import javax.swing.JPanel;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
import org.openide.util.lookup.ServiceProviders;
-import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
@@ -35,13 +37,12 @@ import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
* add data source wizard. It also provides a run method overload to allow it to
* be used independently of the wizard.
*/
-//@ServiceProviders(value={
-// @ServiceProvider(service=DataSourceProcessor.class),
-// @ServiceProvider(service=AutoIngestDataSourceProcessor.class)}
-//)
+@ServiceProviders(value={
+ @ServiceProvider(service=AutoIngestDataSourceProcessor.class)}
+)
@NbBundle.Messages({
"ArchiveDSP.dsType.text=Archive file"})
-public class ArchiveExtractorDSProcessor implements DataSourceProcessor, AutoIngestDataSourceProcessor {
+public class ArchiveExtractorDSProcessor implements AutoIngestDataSourceProcessor {
private final static String DATA_SOURCE_TYPE = Bundle.ArchiveDSP_dsType_text();
@@ -50,6 +51,8 @@ public class ArchiveExtractorDSProcessor implements DataSourceProcessor, AutoIng
private String archivePath;
private boolean setDataSourceOptionsCalled;
+ private final ExecutorService jobProcessingExecutor;
+ private static final String ARCHIVE_DSP_THREAD_NAME = "Archive-DSP-%d";
private AddArchiveTask addArchiveTask;
/**
@@ -60,6 +63,7 @@ public class ArchiveExtractorDSProcessor implements DataSourceProcessor, AutoIng
*/
public ArchiveExtractorDSProcessor() {
configPanel = ArchiveFilePanel.createInstance(ArchiveExtractorDSProcessor.class.getName(), ArchiveUtil.getArchiveFilters());
+ jobProcessingExecutor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(ARCHIVE_DSP_THREAD_NAME).build());
}
@Override
@@ -151,21 +155,15 @@ public class ArchiveExtractorDSProcessor implements DataSourceProcessor, AutoIng
*/
public void run(String deviceId, String archivePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
addArchiveTask = new AddArchiveTask(deviceId, archivePath, progressMonitor, callback);
- new Thread(addArchiveTask).start();
+ jobProcessingExecutor.submit(addArchiveTask);
}
/**
- * Requests cancellation of the background task that adds a data source to
- * the case database, after the task is started using the run method. This
- * is a "best effort" cancellation, with no guarantees that the case
- * database will be unchanged. If cancellation succeeded, the list of new
- * data sources returned by the background task will be empty.
+ * This DSP is a service to AutoIngestDataSourceProcessor only. Hence it is
+ * only used by AIM. AIM currently doesn't support DSP cancellation.
*/
@Override
public void cancel() {
- if (null != addArchiveTask) {
- addArchiveTask.cancelTask();
- }
}
@Override
@@ -175,50 +173,4 @@ public class ArchiveExtractorDSProcessor implements DataSourceProcessor, AutoIng
configPanel.reset();
setDataSourceOptionsCalled = false;
}
-
- /**
- * Extracts the contents of a ZIP archive submitted as a data source to a
- * subdirectory of the auto ingest module output directory.
- *
- * @throws IOException if there is a problem extracting the data source from
- * the archive.
-
- private static Path extractDataSource(Path outputDirectoryPath, Path dataSourcePath) throws IOException {
- String dataSourceFileNameNoExt = FilenameUtils.removeExtension(dataSourcePath.getFileName().toString());
- Path destinationFolder = Paths.get(outputDirectoryPath.toString(),
- AUTO_INGEST_MODULE_OUTPUT_DIR,
- dataSourceFileNameNoExt + "_" + TimeStampUtils.createTimeStamp());
- Files.createDirectories(destinationFolder);
-
- int BUFFER_SIZE = 524288; // Read/write 500KB at a time
- File sourceZipFile = dataSourcePath.toFile();
- ZipFile zipFile;
- zipFile = new ZipFile(sourceZipFile, ZipFile.OPEN_READ);
- Enumeration extends ZipEntry> zipFileEntries = zipFile.entries();
- try {
- while (zipFileEntries.hasMoreElements()) {
- ZipEntry entry = zipFileEntries.nextElement();
- String currentEntry = entry.getName();
- File destFile = new File(destinationFolder.toString(), currentEntry);
- destFile = new File(destinationFolder.toString(), destFile.getName());
- File destinationParent = destFile.getParentFile();
- destinationParent.mkdirs();
- if (!entry.isDirectory()) {
- BufferedInputStream is = new BufferedInputStream(zipFile.getInputStream(entry));
- int currentByte;
- byte data[] = new byte[BUFFER_SIZE];
- try (FileOutputStream fos = new FileOutputStream(destFile); BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER_SIZE)) {
- currentByte = is.read(data, 0, BUFFER_SIZE);
- while (currentByte != -1) {
- dest.write(data, 0, currentByte);
- currentByte = is.read(data, 0, BUFFER_SIZE);
- }
- }
- }
- }
- } finally {
- zipFile.close();
- }
- return destinationFolder;
- } */
}
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ArchiveUtil.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ArchiveUtil.java
index b7a2926092..db2b954bca 100755
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ArchiveUtil.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ArchiveUtil.java
@@ -214,10 +214,11 @@ final class ArchiveUtil {
* @param destinationFolder Path to directory where results will be
* extracted to.
*
+ * @return List of file names contained within archive
* @throws
* ArchiveExtractionException
*/
- static void unpackArchiveFile(String archiveFilePath, String destinationFolder) throws ArchiveExtractionException {
+ static List unpackArchiveFile(String archiveFilePath, String destinationFolder) throws ArchiveExtractionException {
if (!SevenZip.isInitializedSuccessfully() && (SevenZip.getLastInitializationException() == null)) {
try {
SevenZip.initSevenZipFromPlatformJAR();
@@ -225,6 +226,7 @@ final class ArchiveUtil {
throw new ArchiveExtractionException("Unable to initialize 7Zip libraries", ex);
}
}
+ List files = new ArrayList<>();
ISevenZipInArchive inArchive = null;
try {
RandomAccessFile randomAccessFile = new RandomAccessFile(new File(archiveFilePath), "r");
@@ -251,6 +253,8 @@ final class ArchiveUtil {
}
}
}
+ // keep track of extracted files
+ files.add(fullPath.toString());
}
} catch (Exception ex) {
throw new ArchiveExtractionException("Exception while unpacking archive contents", ex);
@@ -263,6 +267,7 @@ final class ArchiveUtil {
throw new ArchiveExtractionException("Exception while closing the archive", ex);
}
}
+ return files;
}
/**
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/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.form b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.form
index ad525e92ee..f00e28374c 100755
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.form
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.form
@@ -17,46 +17,22 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
@@ -73,8 +49,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
@@ -99,9 +103,9 @@
-
+
-
+
@@ -135,16 +139,13 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -234,6 +235,15 @@
+
+
+
+
+
+
+
+
+
@@ -247,6 +257,15 @@
+
+
+
+
+
+
+
+
+
@@ -290,6 +309,15 @@
+
+
+
+
+
+
+
+
+
@@ -303,6 +331,15 @@
+
+
+
+
+
+
+
+
+
@@ -316,6 +353,15 @@
+
+
+
+
+
+
+
+
+
@@ -330,6 +376,15 @@
+
+
+
+
+
+
+
+
+
@@ -343,6 +398,15 @@
+
+
+
+
+
+
+
+
+
@@ -356,6 +420,15 @@
+
+
+
+
+
+
+
+
+
@@ -369,6 +442,15 @@
+
+
+
+
+
+
+
+
+
@@ -382,6 +464,15 @@
+
+
+
+
+
+
+
+
+
@@ -422,6 +513,15 @@
+
+
+
+
+
+
+
+
+
@@ -456,20 +556,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java
index 891975223a..be8abbd1ee 100755
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java
@@ -39,7 +39,6 @@ import javax.swing.DefaultListSelectionModel;
import java.awt.Color;
import java.beans.PropertyChangeEvent;
import java.io.File;
-import java.util.Collections;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
@@ -60,10 +59,13 @@ import org.sleuthkit.autopsy.core.ServicesMonitor;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
-import org.sleuthkit.autopsy.ingest.IngestManager;
-import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotDialog;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestManager.CaseDeletionResult;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestManager.JobsSnapshot;
+import org.sleuthkit.autopsy.guiutils.DurationCellRenderer;
+import org.sleuthkit.autopsy.guiutils.LongDateCellRenderer;
+import org.sleuthkit.autopsy.guiutils.StatusIconCellRenderer;
+import org.sleuthkit.autopsy.ingest.IngestManager;
+import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotDialog;
/**
* A panel for monitoring automated ingest by a cluster, and for controlling
@@ -71,6 +73,7 @@ import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestManager.JobsSnaps
* one such panel per node.
*/
@Messages({
+ "AutoIngestControlPanel.bnClusterMetrics.text=Cluster Metrics",
"AutoIngestControlPanel.bnPause.text=Pause",
"AutoIngestControlPanel.bnPause.paused=Paused",
"AutoIngestControlPanel.bnPause.running=Running",
@@ -114,7 +117,7 @@ import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestManager.JobsSnaps
"AutoIngestControlPanel.bnPrioritizeJob.actionCommand=",
"AutoIngestControlPanel.lbServicesStatus.text=Services Status:",
"AutoIngestControlPanel.tbServicesStatusMessage.text=",
- "AutoIngestControlPanel.bnOpenLogDir.text=Open System Logs Directory",
+ "AutoIngestControlPanel.bnOpenLogDir.text=Open System Logs Folder",
"AutoIngestControlPanel.bnReprocessJob.text=Reprocess Job",
"AutoIngestControlPanel.bnPrioritizeFolder.label=",
"AutoIngestControlPanel.Cancelling=Cancelling...",
@@ -138,6 +141,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
private static final int GENERIC_COL_MAX_WIDTH = 2000;
private static final int PENDING_TABLE_COL_PREFERRED_WIDTH = 280;
private static final int RUNNING_TABLE_COL_PREFERRED_WIDTH = 175;
+ private static final int PRIORITY_COLUMN_PREFERRED_WIDTH = 60;
+ private static final int PRIORITY_COLUMN_MAX_WIDTH = 150;
private static final int ACTIVITY_TIME_COL_MIN_WIDTH = 250;
private static final int ACTIVITY_TIME_COL_MAX_WIDTH = 450;
private static final int TIME_COL_MIN_WIDTH = 30;
@@ -177,6 +182,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
* ordinal or a column header string.
*/
@Messages({
+ "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority=Prioritized",
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.Case=Case",
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.ImageFolder=Data Source",
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.HostName=Host Name",
@@ -203,8 +209,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
STATUS(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Status")),
CASE_DIRECTORY_PATH(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.CaseFolder")),
IS_LOCAL_JOB(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.LocalJob")),
- MANIFEST_FILE_PATH(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ManifestFilePath"));
-
+ MANIFEST_FILE_PATH(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ManifestFilePath")),
+ PRIORITY(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority"));
private final String header;
private JobsTableModelColumns(String header) {
@@ -227,7 +233,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
STAGE_TIME.getColumnHeader(),
CASE_DIRECTORY_PATH.getColumnHeader(),
IS_LOCAL_JOB.getColumnHeader(),
- MANIFEST_FILE_PATH.getColumnHeader()};
+ MANIFEST_FILE_PATH.getColumnHeader(),
+ PRIORITY.getColumnHeader()};
}
/**
@@ -259,32 +266,11 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
manager = AutoIngestManager.getInstance();
- pendingTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) {
- private static final long serialVersionUID = 1L;
+ pendingTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0);
- @Override
- public boolean isCellEditable(int row, int column) {
- return false;
- }
- };
+ runningTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0);
- runningTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) {
- private static final long serialVersionUID = 1L;
-
- @Override
- public boolean isCellEditable(int row, int column) {
- return false;
- }
- };
-
- completedTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) {
- private static final long serialVersionUID = 1L;
-
- @Override
- public boolean isCellEditable(int row, int column) {
- return false;
- }
- };
+ completedTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0);
initComponents(); // Generated code.
setServicesStatusMessage();
@@ -292,7 +278,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
initRunningJobsTable();
initCompletedJobsTable();
initButtons();
-
+ completedTable.getRowSorter().toggleSortOrder(JobsTableModelColumns.COMPLETED_TIME.ordinal());
/*
* Must set this flag, otherwise pop up menus don't close properly.
*/
@@ -412,10 +398,16 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
column.setPreferredWidth(TIME_COL_PREFERRED_WIDTH);
column.setWidth(TIME_COL_PREFERRED_WIDTH);
+ column = pendingTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader());
+ column.setCellRenderer(new PrioritizedIconCellRenderer());
+ column.setMaxWidth(PRIORITY_COLUMN_MAX_WIDTH);
+ column.setPreferredWidth(PRIORITY_COLUMN_PREFERRED_WIDTH);
+ column.setWidth(PRIORITY_COLUMN_PREFERRED_WIDTH);
+
/**
- * Prevent sorting when a column header is clicked.
+ * Allow sorting when a column header is clicked.
*/
- pendingTable.setAutoCreateRowSorter(false);
+ pendingTable.setRowSorter(new AutoIngestRowSorter<>(pendingTableModel));
/*
* Create a row selection listener to enable/disable the prioritize
@@ -454,7 +446,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.IS_LOCAL_JOB.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader()));
-
+ runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader()));
/*
* Set up a column to display the cases associated with the jobs.
*/
@@ -524,9 +516,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
}
private void updateRunningTableButtonsBasedOnSelectedRow() {
- int row = runningTable.getSelectedRow();
+ int row = runningTable.convertRowIndexToModel(runningTable.getSelectedRow());
if (row >= 0 && row < runningTable.getRowCount()) {
- if ((boolean) runningTableModel.getValueAt(row, JobsTableModelColumns.IS_LOCAL_JOB.ordinal())) {
+ if ((boolean) runningTable.getModel().getValueAt(row, JobsTableModelColumns.IS_LOCAL_JOB.ordinal())) {
enableRunningTableButtons(true);
return;
}
@@ -544,13 +536,13 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
* does not remove the columns from the model, just from this table.
*/
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.STARTED_TIME.getColumnHeader()));
+ completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.HOST_NAME.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.STAGE.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.STAGE_TIME.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.IS_LOCAL_JOB.getColumnHeader()));
- completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.HOST_NAME.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader()));
-
+ completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader()));
/*
* Set up a column to display the cases associated with the jobs.
*/
@@ -596,16 +588,16 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
* renderer that will choose an icon to represent the job status.
*/
column = completedTable.getColumn(JobsTableModelColumns.STATUS.getColumnHeader());
- column.setCellRenderer(new CaseStatusIconCellRenderer());
+ column.setCellRenderer(new StatusIconCellRenderer());
column.setMinWidth(STATUS_COL_MIN_WIDTH);
column.setMaxWidth(STATUS_COL_MAX_WIDTH);
column.setPreferredWidth(STATUS_COL_PREFERRED_WIDTH);
column.setWidth(STATUS_COL_PREFERRED_WIDTH);
/*
- * Prevent sorting when a column header is clicked.
+ * Allow sorting when a column header is clicked.
*/
- completedTable.setAutoCreateRowSorter(false);
+ completedTable.setRowSorter(new AutoIngestRowSorter<>(completedTableModel));
/*
* Create a row selection listener to enable/disable the delete case and
@@ -982,7 +974,6 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
List completedJobs = new ArrayList<>();
manager.getJobs(pendingJobs, runningJobs, completedJobs);
// Sort the completed jobs list by completed date
- Collections.sort(completedJobs, new AutoIngestJob.CompletedDateDescendingComparator());
EventQueue.invokeLater(new RefreshComponentsTask(pendingJobs, runningJobs, completedJobs));
}
}
@@ -1030,9 +1021,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
*/
if (null != pendingJobs) {
- Path currentRow = getSelectedEntry(pendingTable, pendingTableModel);
- refreshTable(pendingJobs, pendingTableModel, null);
- setSelectedEntry(pendingTable, pendingTableModel, currentRow);
+ Path currentRow = getSelectedEntry(pendingTable);
+ refreshTable(pendingJobs, (DefaultTableModel) pendingTable.getModel(), null);
+ setSelectedEntry(pendingTable, currentRow);
}
if (null != runningJobs) {
@@ -1041,15 +1032,15 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
} else {
updateRunningTableButtonsBasedOnSelectedRow();
}
- Path currentRow = getSelectedEntry(runningTable, runningTableModel);
- refreshTable(runningJobs, runningTableModel, null);
- setSelectedEntry(runningTable, runningTableModel, currentRow);
+ Path currentRow = getSelectedEntry(runningTable);
+ refreshTable(runningJobs, (DefaultTableModel) runningTable.getModel(), null);
+ setSelectedEntry(runningTable, currentRow);
}
if (null != completedJobs) {
- Path currentRow = getSelectedEntry(completedTable, completedTableModel);
- refreshTable(completedJobs, completedTableModel, null);
- setSelectedEntry(completedTable, completedTableModel, currentRow);
+ Path currentRow = getSelectedEntry(completedTable);
+ refreshTable(completedJobs, (DefaultTableModel) completedTable.getModel(), null);
+ setSelectedEntry(completedTable, currentRow);
}
}
@@ -1087,12 +1078,12 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
*
* @return a path representing the current selection
*/
- Path getSelectedEntry(JTable table, DefaultTableModel tableModel) {
+ Path getSelectedEntry(JTable table) {
try {
- int currentlySelectedRow = table.getSelectedRow();
+ int currentlySelectedRow = table.convertRowIndexToModel(table.getSelectedRow());
if (currentlySelectedRow >= 0 && currentlySelectedRow < table.getRowCount()) {
- return Paths.get(tableModel.getValueAt(currentlySelectedRow, JobsTableModelColumns.CASE.ordinal()).toString(),
- tableModel.getValueAt(currentlySelectedRow, JobsTableModelColumns.DATA_SOURCE.ordinal()).toString());
+ return Paths.get(table.getModel().getValueAt(currentlySelectedRow, JobsTableModelColumns.CASE.ordinal()).toString(),
+ table.getModel().getValueAt(currentlySelectedRow, JobsTableModelColumns.DATA_SOURCE.ordinal()).toString());
}
} catch (Exception ignored) {
return null;
@@ -1108,12 +1099,12 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
* @param tableModel The tableModel of the table to set
* @param path The path of the item to set
*/
- void setSelectedEntry(JTable table, DefaultTableModel tableModel, Path path) {
+ void setSelectedEntry(JTable table, Path path) {
if (path != null) {
try {
for (int row = 0; row < table.getRowCount(); ++row) {
- Path temp = Paths.get(tableModel.getValueAt(row, JobsTableModelColumns.CASE.ordinal()).toString(),
- tableModel.getValueAt(row, JobsTableModelColumns.DATA_SOURCE.ordinal()).toString());
+ Path temp = Paths.get(table.getModel().getValueAt(row, JobsTableModelColumns.CASE.ordinal()).toString(),
+ table.getModel().getValueAt(row, JobsTableModelColumns.DATA_SOURCE.ordinal()).toString());
if (temp.compareTo(path) == 0) { // found it
table.setRowSelectionInterval(row, row);
return;
@@ -1152,11 +1143,12 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
job.getProcessingStageStartDate(), // STARTED_TIME
job.getCompletedDate(), // COMPLETED_TIME
status.getDescription(), // ACTIVITY
- job.getErrorsOccurred(), // STATUS
+ job.getErrorsOccurred() ? StatusIconCellRenderer.Status.WARNING : StatusIconCellRenderer.Status.OK, // STATUS
((Date.from(Instant.now()).getTime()) - (status.getStartDate().getTime())), // ACTIVITY_TIME
job.getCaseDirectoryPath(), // CASE_DIRECTORY_PATH
job.getProcessingHostName().equals(LOCAL_HOST_NAME), // IS_LOCAL_JOB
- job.getManifest().getFilePath()}); // MANIFEST_FILE_PATH
+ job.getManifest().getFilePath(), // MANIFEST_FILE_PATH
+ job.getPriority()}); // PRIORITY
}
} catch (Exception ex) {
SYS_LOGGER.log(Level.SEVERE, "Dashboard error refreshing table", ex);
@@ -1168,9 +1160,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
*/
private void refreshTables() {
JobsSnapshot jobsSnapshot = manager.getCurrentJobsSnapshot();
- refreshTable(jobsSnapshot.getCompletedJobs(), completedTableModel, null);
- refreshTable(jobsSnapshot.getPendingJobs(), pendingTableModel, null);
- refreshTable(jobsSnapshot.getRunningJobs(), runningTableModel, null);
+ refreshTable(jobsSnapshot.getCompletedJobs(), (DefaultTableModel) completedTable.getModel(), null);
+ refreshTable(jobsSnapshot.getPendingJobs(), (DefaultTableModel) pendingTable.getModel(), null);
+ refreshTable(jobsSnapshot.getRunningJobs(), (DefaultTableModel) runningTable.getModel(), null);
}
/**
@@ -1207,6 +1199,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
lbServicesStatus = new javax.swing.JLabel();
tbServicesStatusMessage = new javax.swing.JTextField();
bnOpenLogDir = new javax.swing.JButton();
+ bnClusterMetrics = new javax.swing.JButton();
bnReprocessJob = new javax.swing.JButton();
pendingTable.setModel(pendingTableModel);
@@ -1265,6 +1258,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnCancelJob, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnCancelJob.text")); // NOI18N
bnCancelJob.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnCancelJob.toolTipText")); // NOI18N
+ bnCancelJob.setMaximumSize(new java.awt.Dimension(162, 23));
+ bnCancelJob.setMinimumSize(new java.awt.Dimension(162, 23));
+ bnCancelJob.setPreferredSize(new java.awt.Dimension(162, 23));
bnCancelJob.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnCancelJobActionPerformed(evt);
@@ -1273,6 +1269,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnDeleteCase, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnDeleteCase.text")); // NOI18N
bnDeleteCase.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnDeleteCase.toolTipText")); // NOI18N
+ bnDeleteCase.setMaximumSize(new java.awt.Dimension(162, 23));
+ bnDeleteCase.setMinimumSize(new java.awt.Dimension(162, 23));
+ bnDeleteCase.setPreferredSize(new java.awt.Dimension(162, 23));
bnDeleteCase.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnDeleteCaseActionPerformed(evt);
@@ -1290,6 +1289,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnRefresh, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnRefresh.text")); // NOI18N
bnRefresh.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnRefresh.toolTipText")); // NOI18N
+ bnRefresh.setMaximumSize(new java.awt.Dimension(162, 23));
+ bnRefresh.setMinimumSize(new java.awt.Dimension(162, 23));
+ bnRefresh.setPreferredSize(new java.awt.Dimension(162, 23));
bnRefresh.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnRefreshActionPerformed(evt);
@@ -1298,6 +1300,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnCancelModule, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnCancelModule.text")); // NOI18N
bnCancelModule.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnCancelModule.toolTipText")); // NOI18N
+ bnCancelModule.setMaximumSize(new java.awt.Dimension(162, 23));
+ bnCancelModule.setMinimumSize(new java.awt.Dimension(162, 23));
+ bnCancelModule.setPreferredSize(new java.awt.Dimension(162, 23));
bnCancelModule.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnCancelModuleActionPerformed(evt);
@@ -1306,6 +1311,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnExit, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnExit.text")); // NOI18N
bnExit.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnExit.toolTipText")); // NOI18N
+ bnExit.setMaximumSize(new java.awt.Dimension(162, 23));
+ bnExit.setMinimumSize(new java.awt.Dimension(162, 23));
+ bnExit.setPreferredSize(new java.awt.Dimension(162, 23));
bnExit.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnExitActionPerformed(evt);
@@ -1315,6 +1323,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnOptions, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnOptions.text")); // NOI18N
bnOptions.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnOptions.toolTipText")); // NOI18N
bnOptions.setEnabled(false);
+ bnOptions.setMaximumSize(new java.awt.Dimension(162, 23));
+ bnOptions.setMinimumSize(new java.awt.Dimension(162, 23));
+ bnOptions.setPreferredSize(new java.awt.Dimension(162, 23));
bnOptions.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnOptionsActionPerformed(evt);
@@ -1323,6 +1334,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnShowProgress, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnShowProgress.text")); // NOI18N
bnShowProgress.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnShowProgress.toolTipText")); // NOI18N
+ bnShowProgress.setMaximumSize(new java.awt.Dimension(162, 23));
+ bnShowProgress.setMinimumSize(new java.awt.Dimension(162, 23));
+ bnShowProgress.setPreferredSize(new java.awt.Dimension(162, 23));
bnShowProgress.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnShowProgressActionPerformed(evt);
@@ -1331,6 +1345,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnPause, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPause.text")); // NOI18N
bnPause.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPause.toolTipText")); // NOI18N
+ bnPause.setMaximumSize(new java.awt.Dimension(162, 23));
+ bnPause.setMinimumSize(new java.awt.Dimension(162, 23));
+ bnPause.setPreferredSize(new java.awt.Dimension(162, 23));
bnPause.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnPauseActionPerformed(evt);
@@ -1339,6 +1356,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnPrioritizeCase, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPrioritizeCase.text")); // NOI18N
bnPrioritizeCase.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPrioritizeCase.toolTipText")); // NOI18N
+ bnPrioritizeCase.setMaximumSize(new java.awt.Dimension(162, 23));
+ bnPrioritizeCase.setMinimumSize(new java.awt.Dimension(162, 23));
+ bnPrioritizeCase.setPreferredSize(new java.awt.Dimension(162, 23));
bnPrioritizeCase.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnPrioritizeCaseActionPerformed(evt);
@@ -1347,6 +1367,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnShowCaseLog, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnShowCaseLog.text")); // NOI18N
bnShowCaseLog.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnShowCaseLog.toolTipText")); // NOI18N
+ bnShowCaseLog.setMaximumSize(new java.awt.Dimension(162, 23));
+ bnShowCaseLog.setMinimumSize(new java.awt.Dimension(162, 23));
+ bnShowCaseLog.setPreferredSize(new java.awt.Dimension(162, 23));
bnShowCaseLog.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnShowCaseLogActionPerformed(evt);
@@ -1364,6 +1387,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnPrioritizeJob, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPrioritizeJob.text")); // NOI18N
bnPrioritizeJob.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPrioritizeJob.toolTipText")); // NOI18N
bnPrioritizeJob.setActionCommand(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPrioritizeJob.actionCommand")); // NOI18N
+ bnPrioritizeJob.setMaximumSize(new java.awt.Dimension(162, 23));
+ bnPrioritizeJob.setMinimumSize(new java.awt.Dimension(162, 23));
+ bnPrioritizeJob.setPreferredSize(new java.awt.Dimension(162, 23));
bnPrioritizeJob.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnPrioritizeJobActionPerformed(evt);
@@ -1379,13 +1405,29 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
tbServicesStatusMessage.setBorder(null);
org.openide.awt.Mnemonics.setLocalizedText(bnOpenLogDir, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnOpenLogDir.text")); // NOI18N
+ bnOpenLogDir.setMaximumSize(new java.awt.Dimension(162, 23));
+ bnOpenLogDir.setMinimumSize(new java.awt.Dimension(162, 23));
+ bnOpenLogDir.setPreferredSize(new java.awt.Dimension(162, 23));
bnOpenLogDir.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnOpenLogDirActionPerformed(evt);
}
});
+ org.openide.awt.Mnemonics.setLocalizedText(bnClusterMetrics, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnClusterMetrics.text")); // NOI18N
+ bnClusterMetrics.setMaximumSize(new java.awt.Dimension(162, 23));
+ bnClusterMetrics.setMinimumSize(new java.awt.Dimension(162, 23));
+ bnClusterMetrics.setPreferredSize(new java.awt.Dimension(162, 23));
+ bnClusterMetrics.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ bnClusterMetricsActionPerformed(evt);
+ }
+ });
+
org.openide.awt.Mnemonics.setLocalizedText(bnReprocessJob, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnReprocessJob.text")); // NOI18N
+ bnReprocessJob.setMaximumSize(new java.awt.Dimension(162, 23));
+ bnReprocessJob.setMinimumSize(new java.awt.Dimension(162, 23));
+ bnReprocessJob.setPreferredSize(new java.awt.Dimension(162, 23));
bnReprocessJob.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnReprocessJobActionPerformed(evt);
@@ -1399,38 +1441,20 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(layout.createSequentialGroup()
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
- .addComponent(lbPending, javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(pendingScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 920, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(bnPrioritizeCase, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- .addComponent(bnPrioritizeJob, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
- .addComponent(bnPause)
- .addGap(18, 18, 18)
- .addComponent(bnRefresh, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addGap(18, 18, 18)
- .addComponent(bnOptions)
- .addGap(18, 18, 18)
- .addComponent(bnOpenLogDir)
- .addGap(18, 18, 18)
- .addComponent(bnExit, javax.swing.GroupLayout.PREFERRED_SIZE, 94, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addGroup(layout.createSequentialGroup()
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(runningScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 920, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addComponent(completedScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 920, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addComponent(bnPause, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
- .addComponent(bnCancelJob, javax.swing.GroupLayout.DEFAULT_SIZE, 117, Short.MAX_VALUE)
- .addComponent(bnShowProgress, javax.swing.GroupLayout.DEFAULT_SIZE, 116, Short.MAX_VALUE)
- .addComponent(bnCancelModule, javax.swing.GroupLayout.DEFAULT_SIZE, 117, Short.MAX_VALUE)
- .addComponent(bnDeleteCase, javax.swing.GroupLayout.DEFAULT_SIZE, 117, Short.MAX_VALUE)
- .addComponent(bnShowCaseLog, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- .addComponent(bnReprocessJob, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
+ .addComponent(bnRefresh, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(bnOptions, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(bnOpenLogDir, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(bnClusterMetrics, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(bnExit, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addComponent(lbStatus)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
@@ -1441,11 +1465,32 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
.addComponent(lbServicesStatus)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(tbServicesStatusMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 861, javax.swing.GroupLayout.PREFERRED_SIZE)))
- .addGap(0, 0, Short.MAX_VALUE)))
- .addContainerGap())
+ .addGap(0, 0, Short.MAX_VALUE))
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(lbPending)
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(runningScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 1021, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(completedScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 1021, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addComponent(bnCancelJob, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(bnShowProgress, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(bnCancelModule, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(bnDeleteCase, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(bnShowCaseLog, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(bnReprocessJob, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(pendingScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 1021, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addComponent(bnPrioritizeCase, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(bnPrioritizeJob, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
);
- layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {bnCancelJob, bnCancelModule, bnDeleteCase, bnExit, bnOpenLogDir, bnOptions, bnPause, bnRefresh, bnShowProgress});
+ layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {bnCancelJob, bnCancelModule, bnDeleteCase, bnShowProgress});
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@@ -1465,48 +1510,47 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
.addComponent(pendingScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addGap(82, 82, 82)
- .addComponent(bnPrioritizeCase)
+ .addComponent(bnPrioritizeCase, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(bnPrioritizeJob)))
+ .addComponent(bnPrioritizeJob, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lbRunning)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(34, 34, 34)
- .addComponent(bnShowProgress)
+ .addComponent(bnShowProgress, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(bnCancelJob)
+ .addComponent(bnCancelJob, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(bnCancelModule))
+ .addComponent(bnCancelModule, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(runningScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 133, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(68, 68, 68)
- .addComponent(bnReprocessJob)
+ .addComponent(bnReprocessJob, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(bnDeleteCase)
+ .addComponent(bnDeleteCase, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(bnShowCaseLog))
+ .addComponent(bnShowCaseLog, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lbCompleted)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(completedScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 179, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(bnExit)
- .addComponent(bnOpenLogDir))
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(bnPause)
- .addComponent(bnRefresh)
- .addComponent(bnOptions)))))
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(bnPause, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(bnRefresh, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(bnOptions, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(bnOpenLogDir, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(bnClusterMetrics, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(bnExit, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))
.addContainerGap())
);
- layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {bnCancelJob, bnCancelModule, bnDeleteCase, bnExit, bnOpenLogDir, bnOptions, bnRefresh, bnShowProgress});
+ layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {bnCancelJob, bnCancelModule, bnClusterMetrics, bnDeleteCase, bnExit, bnOpenLogDir, bnOptions, bnPrioritizeCase, bnPrioritizeJob, bnRefresh, bnShowProgress});
}// //GEN-END:initComponents
@@ -1535,11 +1579,11 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
"AutoIngestControlPanel.DeletionFailed=Deletion failed for job"
})
private void bnDeleteCaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnDeleteCaseActionPerformed
- if (completedTableModel.getRowCount() < 0 || completedTable.getSelectedRow() < 0) {
+ if (completedTable.getModel().getRowCount() < 0 || completedTable.getSelectedRow() < 0) {
return;
}
- String caseName = (String) completedTable.getValueAt(completedTable.getSelectedRow(), JobsTableModelColumns.CASE.ordinal());
+ String caseName = (String) completedTable.getModel().getValueAt(completedTable.convertRowIndexToModel(completedTable.getSelectedRow()), JobsTableModelColumns.CASE.ordinal());
Object[] options = {
org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "ConfirmationDialog.Delete"),
org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "ConfirmationDialog.DoNotDelete")
@@ -1556,8 +1600,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
if (reply == JOptionPane.YES_OPTION) {
bnDeleteCase.setEnabled(false);
bnShowCaseLog.setEnabled(false);
- if (completedTableModel.getRowCount() > 0 && completedTable.getSelectedRow() >= 0) {
- Path caseDirectoryPath = (Path) completedTableModel.getValueAt(completedTable.getSelectedRow(), JobsTableModelColumns.CASE_DIRECTORY_PATH.ordinal());
+ if (completedTable.getModel().getRowCount() > 0 && completedTable.getSelectedRow() >= 0) {
+ Path caseDirectoryPath = (Path) completedTable.getModel().getValueAt(completedTable.convertRowIndexToModel(completedTable.getSelectedRow()), JobsTableModelColumns.CASE_DIRECTORY_PATH.ordinal());
completedTable.clearSelection();
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
CaseDeletionResult result = manager.deleteCase(caseName, caseDirectoryPath);
@@ -1703,9 +1747,10 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
*/
@Messages({"AutoIngestControlPanel.casePrioritization.errorMessage=An error occurred when prioritizing the case. Some or all jobs may not have been prioritized."})
private void bnPrioritizeCaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnPrioritizeCaseActionPerformed
- if (pendingTableModel.getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) {
+ if (pendingTable.getModel().getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) {
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
- String caseName = (pendingTableModel.getValueAt(pendingTable.getSelectedRow(), JobsTableModelColumns.CASE.ordinal())).toString();
+
+ String caseName = (pendingTable.getModel().getValueAt(pendingTable.convertRowIndexToModel(pendingTable.getSelectedRow()), JobsTableModelColumns.CASE.ordinal())).toString();
try {
manager.prioritizeCase(caseName);
} catch (AutoIngestManager.AutoIngestManagerException ex) {
@@ -1731,9 +1776,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
})
private void bnShowCaseLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnShowCaseLogActionPerformed
try {
- int selectedRow = completedTable.getSelectedRow();
+ int selectedRow = completedTable.convertRowIndexToModel(completedTable.getSelectedRow());
if (selectedRow != -1) {
- Path caseDirectoryPath = (Path) completedTableModel.getValueAt(selectedRow, JobsTableModelColumns.CASE_DIRECTORY_PATH.ordinal());
+ Path caseDirectoryPath = (Path) completedTable.getModel().getValueAt(selectedRow, JobsTableModelColumns.CASE_DIRECTORY_PATH.ordinal());
if (null != caseDirectoryPath) {
Path pathToLog = AutoIngestJobLogger.getLogPath(caseDirectoryPath);
if (pathToLog.toFile().exists()) {
@@ -1762,9 +1807,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
@Messages({"AutoIngestControlPanel.jobPrioritization.errorMessage=An error occurred when prioritizing the job."})
private void bnPrioritizeJobActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnPrioritizeJobActionPerformed
- if (pendingTableModel.getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) {
+ if (pendingTable.getModel().getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) {
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
- Path manifestFilePath = (Path) (pendingTableModel.getValueAt(pendingTable.getSelectedRow(), JobsTableModelColumns.MANIFEST_FILE_PATH.ordinal()));
+ Path manifestFilePath = (Path) (pendingTable.getModel().getValueAt(pendingTable.convertRowIndexToModel(pendingTable.getSelectedRow()), JobsTableModelColumns.MANIFEST_FILE_PATH.ordinal()));
try {
manager.prioritizeJob(manifestFilePath);
} catch (AutoIngestManager.AutoIngestManagerException ex) {
@@ -1791,19 +1836,28 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
}//GEN-LAST:event_bnOpenLogDirActionPerformed
private void bnReprocessJobActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnReprocessJobActionPerformed
- if (completedTableModel.getRowCount() < 0 || completedTable.getSelectedRow() < 0) {
+ if (completedTable.getModel().getRowCount() < 0 || completedTable.getSelectedRow() < 0) {
return;
}
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
- Path manifestPath = (Path) completedTableModel.getValueAt(completedTable.getSelectedRow(), JobsTableModelColumns.MANIFEST_FILE_PATH.ordinal());
+ Path manifestPath = (Path) completedTable.getModel().getValueAt(completedTable.convertRowIndexToModel(completedTable.getSelectedRow()), JobsTableModelColumns.MANIFEST_FILE_PATH.ordinal());
manager.reprocessJob(manifestPath);
refreshTables();
AutoIngestControlPanel.this.setCursor(Cursor.getDefaultCursor());
}//GEN-LAST:event_bnReprocessJobActionPerformed
+ private void bnClusterMetricsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnClusterMetricsActionPerformed
+ try {
+ new AutoIngestMetricsDialog(this.getTopLevelAncestor());
+ } catch (AutoIngestMetricsDialog.AutoIngestMetricsDialogException ex) {
+ MessageNotifyUtil.Message.error(ex.getMessage());
+ }
+ }//GEN-LAST:event_bnClusterMetricsActionPerformed
+
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton bnCancelJob;
private javax.swing.JButton bnCancelModule;
+ private javax.swing.JButton bnClusterMetrics;
private javax.swing.JButton bnDeleteCase;
private javax.swing.JButton bnExit;
private javax.swing.JButton bnOpenLogDir;
@@ -1830,4 +1884,33 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
private javax.swing.JTextField tbStatusMessage;
// End of variables declaration//GEN-END:variables
+ private class AutoIngestTableModel extends DefaultTableModel {
+
+ private static final long serialVersionUID = 1L;
+
+ private AutoIngestTableModel(String[] headers, int i) {
+ super(headers, i);
+ }
+
+ @Override
+ public boolean isCellEditable(int row, int column) {
+ return false;
+ }
+
+ @Override
+ public Class> getColumnClass(int columnIndex) {
+ if (columnIndex == JobsTableModelColumns.PRIORITY.ordinal()) {
+ return Integer.class;
+ } else if (columnIndex == JobsTableModelColumns.CREATED_TIME.ordinal()
+ || columnIndex == JobsTableModelColumns.COMPLETED_TIME.ordinal()
+ || columnIndex == JobsTableModelColumns.STARTED_TIME.ordinal()
+ || columnIndex == JobsTableModelColumns.STAGE_TIME.ordinal()) {
+ return Date.class;
+ } else if (columnIndex == JobsTableModelColumns.STATUS.ordinal()) {
+ return Boolean.class;
+ } else {
+ return super.getColumnClass(columnIndex);
+ }
+ }
+ }
}
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.form b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.form
index 4a943b4924..78ae8fb2a4 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 @@
+
@@ -103,7 +106,6 @@
-
@@ -127,7 +129,6 @@
-
@@ -151,7 +152,6 @@
-
@@ -255,5 +255,15 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java
index 2d10dff258..421b1f92f0 100755
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java
@@ -44,17 +44,22 @@ import org.sleuthkit.autopsy.core.ServicesMonitor;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestMonitor.JobsSnapshot;
+import org.sleuthkit.autopsy.guiutils.DurationCellRenderer;
+import org.sleuthkit.autopsy.guiutils.LongDateCellRenderer;
+import org.sleuthkit.autopsy.guiutils.StatusIconCellRenderer;
/**
* A dashboard for monitoring an automated ingest cluster.
*/
-public final class AutoIngestDashboard extends JPanel implements Observer {
+final class AutoIngestDashboard extends JPanel implements Observer {
private static final long serialVersionUID = 1L;
private static final int GENERIC_COL_MIN_WIDTH = 30;
private static final int GENERIC_COL_MAX_WIDTH = 2000;
private static final int PENDING_TABLE_COL_PREFERRED_WIDTH = 280;
private static final int RUNNING_TABLE_COL_PREFERRED_WIDTH = 175;
+ private static final int PRIORITY_COLUMN_PREFERRED_WIDTH = 60;
+ private static final int PRIORITY_COLUMN_MAX_WIDTH = 150;
private static final int STAGE_TIME_COL_MIN_WIDTH = 250;
private static final int STAGE_TIME_COL_MAX_WIDTH = 450;
private static final int TIME_COL_MIN_WIDTH = 30;
@@ -100,32 +105,11 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
* Constructs a panel for monitoring an automated ingest cluster.
*/
private AutoIngestDashboard() {
- pendingTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) {
- private static final long serialVersionUID = 1L;
+ pendingTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0);
- @Override
- public boolean isCellEditable(int row, int column) {
- return false;
- }
- };
+ runningTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0);
- runningTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) {
- private static final long serialVersionUID = 1L;
-
- @Override
- public boolean isCellEditable(int row, int column) {
- return false;
- }
- };
-
- completedTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) {
- private static final long serialVersionUID = 1L;
-
- @Override
- public boolean isCellEditable(int row, int column) {
- return false;
- }
- };
+ completedTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0);
initComponents();
setServicesStatusMessage();
@@ -243,10 +227,15 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
column.setPreferredWidth(TIME_COL_PREFERRED_WIDTH);
column.setWidth(TIME_COL_PREFERRED_WIDTH);
- /**
- * Prevent sorting when a column header is clicked.
+ column = pendingTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader());
+ column.setCellRenderer(new PrioritizedIconCellRenderer());
+ column.setMaxWidth(PRIORITY_COLUMN_MAX_WIDTH);
+ column.setPreferredWidth(PRIORITY_COLUMN_PREFERRED_WIDTH);
+ column.setWidth(PRIORITY_COLUMN_PREFERRED_WIDTH);
+ /*
+ * Allow sorting when a column header is clicked.
*/
- pendingTable.setAutoCreateRowSorter(false);
+ pendingTable.setRowSorter(new AutoIngestRowSorter<>(pendingTableModel));
/*
* Create a row selection listener to enable/disable the Prioritize
@@ -257,8 +246,8 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
return;
}
int row = pendingTable.getSelectedRow();
-
- boolean enablePrioritizeButtons = (row >= 0 && row < pendingTable.getRowCount());
+
+ boolean enablePrioritizeButtons = (row >= 0 && row < pendingTable.getRowCount());
this.prioritizeJobButton.setEnabled(enablePrioritizeButtons);
this.prioritizeCaseButton.setEnabled(enablePrioritizeButtons);
});
@@ -280,7 +269,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.JOB.getColumnHeader()));
-
+ runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader()));
/*
* Set up a column to display the cases associated with the jobs.
*/
@@ -354,7 +343,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.JOB.getColumnHeader()));
-
+ completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader()));
/*
* Set up a column to display the cases associated with the jobs.
*/
@@ -400,16 +389,15 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
* renderer that will choose an icon to represent the job status.
*/
column = completedTable.getColumn(JobsTableModelColumns.STATUS.getColumnHeader());
- column.setCellRenderer(new CaseStatusIconCellRenderer());
+ column.setCellRenderer(new StatusIconCellRenderer());
column.setMinWidth(STATUS_COL_MIN_WIDTH);
column.setMaxWidth(STATUS_COL_MAX_WIDTH);
column.setPreferredWidth(STATUS_COL_PREFERRED_WIDTH);
column.setWidth(STATUS_COL_PREFERRED_WIDTH);
-
/*
- * Prevent sorting when a column header is clicked.
+ * Allow sorting when a column header is clicked.
*/
- completedTable.setAutoCreateRowSorter(false);
+ completedTable.setRowSorter(new AutoIngestRowSorter<>(completedTableModel));
}
/**
@@ -472,10 +460,11 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
job.getProcessingStageStartDate(), // STARTED_TIME
job.getCompletedDate(), // COMPLETED_TIME
status.getDescription(), // STAGE
- job.getErrorsOccurred(), // STATUS
+ job.getErrorsOccurred() ? StatusIconCellRenderer.Status.WARNING : StatusIconCellRenderer.Status.OK, // STATUS
((Date.from(Instant.now()).getTime()) - (status.getStartDate().getTime())), // STAGE_TIME
job.getCaseDirectoryPath(), // CASE_DIRECTORY_PATH
job.getManifest().getFilePath(), // MANIFEST_FILE_PATH
+ job.getPriority(), // PRIORITY
job
});
}
@@ -541,6 +530,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
* described by either an enum ordinal or a column header string.
*/
private enum JobsTableModelColumns {
+ @Messages({"AutoIngestDashboard.JobsTableModel.ColumnHeader.Priority=Prioritized"})
CASE(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Case")),
DATA_SOURCE(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.ImageFolder")),
@@ -553,6 +543,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
STATUS(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Status")),
CASE_DIRECTORY_PATH(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.CaseFolder")),
MANIFEST_FILE_PATH(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.ManifestFilePath")),
+ PRIORITY(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Priority")),
JOB(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Job"));
private final String header;
@@ -577,6 +568,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
STAGE_TIME.getColumnHeader(),
CASE_DIRECTORY_PATH.getColumnHeader(),
MANIFEST_FILE_PATH.getColumnHeader(),
+ PRIORITY.getColumnHeader(),
JOB.getColumnHeader()
};
};
@@ -662,12 +654,12 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
tbServicesStatusMessage = new javax.swing.JTextField();
prioritizeJobButton = new javax.swing.JButton();
prioritizeCaseButton = new javax.swing.JButton();
+ clusterMetricsButton = new javax.swing.JButton();
org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.jButton1.text")); // NOI18N
pendingTable.setModel(pendingTableModel);
pendingTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.pendingTable.toolTipText")); // NOI18N
- pendingTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
pendingTable.setRowHeight(20);
pendingTable.setSelectionModel(new DefaultListSelectionModel() {
private static final long serialVersionUID = 1L;
@@ -685,7 +677,6 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
runningTable.setModel(runningTableModel);
runningTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.runningTable.toolTipText")); // NOI18N
- runningTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
runningTable.setRowHeight(20);
runningTable.setSelectionModel(new DefaultListSelectionModel() {
private static final long serialVersionUID = 1L;
@@ -703,7 +694,6 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
completedTable.setModel(completedTableModel);
completedTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.completedTable.toolTipText")); // NOI18N
- completedTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
completedTable.setRowHeight(20);
completedTable.setSelectionModel(new DefaultListSelectionModel() {
private static final long serialVersionUID = 1L;
@@ -762,6 +752,13 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
}
});
+ org.openide.awt.Mnemonics.setLocalizedText(clusterMetricsButton, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.clusterMetricsButton.text")); // NOI18N
+ clusterMetricsButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ clusterMetricsButtonActionPerformed(evt);
+ }
+ });
+
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
@@ -770,24 +767,26 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(pendingScrollPane)
+ .addComponent(runningScrollPane, javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(completedScrollPane, javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(lbPending)
- .addComponent(lbCompleted)
- .addComponent(lbRunning)
- .addGroup(layout.createSequentialGroup()
- .addComponent(lbServicesStatus)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addComponent(tbServicesStatusMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 861, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(refreshButton, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(prioritizeJobButton, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(prioritizeCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)))
- .addGap(0, 0, Short.MAX_VALUE))
- .addComponent(runningScrollPane, javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(completedScrollPane, javax.swing.GroupLayout.Alignment.LEADING))
+ .addComponent(prioritizeCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(clusterMetricsButton))
+ .addComponent(lbPending, javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(lbCompleted, javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(lbRunning, javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
+ .addComponent(lbServicesStatus)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(tbServicesStatusMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 861, javax.swing.GroupLayout.PREFERRED_SIZE)))
+ .addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
@@ -813,7 +812,8 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(refreshButton)
.addComponent(prioritizeJobButton)
- .addComponent(prioritizeCaseButton))
+ .addComponent(prioritizeCaseButton)
+ .addComponent(clusterMetricsButton))
.addContainerGap())
);
}// //GEN-END:initComponents
@@ -872,7 +872,16 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
}
}//GEN-LAST:event_prioritizeCaseButtonActionPerformed
+ private void clusterMetricsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_clusterMetricsButtonActionPerformed
+ try {
+ new AutoIngestMetricsDialog(this.getTopLevelAncestor());
+ } catch (AutoIngestMetricsDialog.AutoIngestMetricsDialogException ex) {
+ MessageNotifyUtil.Message.error(ex.getMessage());
+ }
+ }//GEN-LAST:event_clusterMetricsButtonActionPerformed
+
// Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton clusterMetricsButton;
private javax.swing.JScrollPane completedScrollPane;
private javax.swing.JTable completedTable;
private javax.swing.JButton jButton1;
@@ -890,4 +899,33 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
private javax.swing.JTextField tbServicesStatusMessage;
// End of variables declaration//GEN-END:variables
+ private class AutoIngestTableModel extends DefaultTableModel {
+
+ private static final long serialVersionUID = 1L;
+
+ private AutoIngestTableModel(String[] headers, int i) {
+ super(headers, i);
+ }
+
+ @Override
+ public boolean isCellEditable(int row, int column) {
+ return false;
+ }
+
+ @Override
+ public Class> getColumnClass(int columnIndex) {
+ if (columnIndex == JobsTableModelColumns.PRIORITY.ordinal()) {
+ return Integer.class;
+ } else if (columnIndex == JobsTableModelColumns.CREATED_TIME.ordinal()
+ || columnIndex == JobsTableModelColumns.COMPLETED_TIME.ordinal()
+ || columnIndex == JobsTableModelColumns.STARTED_TIME.ordinal()
+ || columnIndex == JobsTableModelColumns.STAGE_TIME.ordinal()) {
+ return Date.class;
+ } else if (columnIndex == JobsTableModelColumns.STATUS.ordinal()) {
+ return Boolean.class;
+ } else {
+ return super.getColumnClass(columnIndex);
+ }
+ }
+ }
}
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/DataSource.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDataSource.java
similarity index 96%
rename from Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/DataSource.java
rename to Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDataSource.java
index db9d3d5ad9..89a0d0ad5f 100755
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/DataSource.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDataSource.java
@@ -26,7 +26,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback
import org.sleuthkit.datamodel.Content;
@ThreadSafe
-class DataSource {
+class AutoIngestDataSource {
private final String deviceId;
private final Path path;
@@ -34,7 +34,7 @@ class DataSource {
private List errorMessages;
private List content;
- DataSource(String deviceId, Path path) {
+ AutoIngestDataSource(String deviceId, Path path) {
this.deviceId = deviceId;
this.path = path;
}
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java
index 2f2f22fb0d..35b563b961 100755
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java
@@ -62,7 +62,9 @@ import org.openide.util.Lookup;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
import org.sleuthkit.autopsy.casemodule.CaseActionException;
+import org.sleuthkit.autopsy.casemodule.CaseDetails;
import org.sleuthkit.autopsy.casemodule.CaseMetadata;
+import org.sleuthkit.autopsy.coordinationservice.CaseNodeData;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.Lock;
@@ -77,7 +79,6 @@ import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import org.sleuthkit.autopsy.events.AutopsyEvent;
import org.sleuthkit.autopsy.events.AutopsyEventException;
import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
-import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestAlertFile.AutoIngestAlertFileException;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobLogger.AutoIngestJobLoggerException;
import org.sleuthkit.autopsy.experimental.autoingest.FileExporter.FileExportException;
import org.sleuthkit.autopsy.experimental.autoingest.ManifestFileParser.ManifestFileParserException;
@@ -112,12 +113,11 @@ import org.sleuthkit.autopsy.ingest.IngestModuleError;
* The activities of the auto ingest nodes in a cluster are coordinated by way
* of a coordination service and the nodes communicate via event messages.
*/
-public final class AutoIngestManager extends Observable implements PropertyChangeListener {
+final class AutoIngestManager extends Observable implements PropertyChangeListener {
private static final int NUM_INPUT_SCAN_SCHEDULING_THREADS = 1;
private static final String INPUT_SCAN_SCHEDULER_THREAD_NAME = "AIM-input-scan-scheduler-%d";
private static final String INPUT_SCAN_THREAD_NAME = "AIM-input-scan-%d";
- private static int DEFAULT_JOB_PRIORITY = 0;
private static final String AUTO_INGEST_THREAD_NAME = "AIM-job-processing-%d";
private static final String LOCAL_HOST_NAME = NetworkUtils.getLocalHostName();
private static final String EVENT_CHANNEL_NAME = "Auto-Ingest-Manager-Events";
@@ -498,6 +498,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
}
SYS_LOGGER.log(Level.INFO, "Starting input scan of {0}", rootInputDirectory);
InputDirScanner scanner = new InputDirScanner();
+
scanner.scan();
SYS_LOGGER.log(Level.INFO, "Completed input scan of {0}", rootInputDirectory);
}
@@ -553,10 +554,12 @@ public final class AutoIngestManager extends Observable implements PropertyChang
if (!prioritizedJobs.isEmpty()) {
++maxPriority;
for (AutoIngestJob job : prioritizedJobs) {
+ int oldPriority = job.getPriority();
+ job.setPriority(maxPriority);
try {
- this.updateCoordinationServiceNode(job);
- job.setPriority(maxPriority);
+ this.updateCoordinationServiceManifestNode(job);
} catch (CoordinationServiceException | InterruptedException ex) {
+ job.setPriority(oldPriority);
throw new AutoIngestManagerException("Error updating case priority", ex);
}
}
@@ -602,17 +605,19 @@ public final class AutoIngestManager extends Observable implements PropertyChang
}
/*
- * Bump the priority by one and update the coordination service node
- * data for the job.
+ * Bump the priority by one and update the coordination service
+ * manifest node data for the job.
*/
if (null != prioritizedJob) {
++maxPriority;
+ int oldPriority = prioritizedJob.getPriority();
+ prioritizedJob.setPriority(maxPriority);
try {
- this.updateCoordinationServiceNode(prioritizedJob);
+ this.updateCoordinationServiceManifestNode(prioritizedJob);
} catch (CoordinationServiceException | InterruptedException ex) {
+ prioritizedJob.setPriority(oldPriority);
throw new AutoIngestManagerException("Error updating job priority", ex);
}
- prioritizedJob.setPriority(maxPriority);
}
Collections.sort(pendingJobs, new AutoIngestJob.PriorityComparator());
@@ -649,7 +654,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
/*
* Add the job to the pending jobs queue and update the coordination
- * service node data for the job.
+ * service manifest node data for the job.
*/
if (null != completedJob && !completedJob.getCaseDirectoryPath().toString().isEmpty()) {
try {
@@ -661,7 +666,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
completedJob.setCompletedDate(new Date(0));
completedJob.setProcessingStatus(PENDING);
completedJob.setProcessingStage(AutoIngestJob.Stage.PENDING, Date.from(Instant.now()));
- updateCoordinationServiceNode(completedJob);
+ updateCoordinationServiceManifestNode(completedJob);
pendingJobs.add(completedJob);
} catch (CoordinationServiceException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Coordination service error while reprocessing %s", manifestPath), ex);
@@ -755,7 +760,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString()));
AutoIngestJob deletedJob = new AutoIngestJob(nodeData);
deletedJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.DELETED);
- this.updateCoordinationServiceNode(deletedJob);
+ this.updateCoordinationServiceManifestNode(deletedJob);
} catch (AutoIngestJobNodeData.InvalidDataException | AutoIngestJobException ex) {
SYS_LOGGER.log(Level.WARNING, String.format("Invalid auto ingest job node data for %s", manifestPath), ex);
return CaseDeletionResult.PARTIALLY_DELETED;
@@ -865,21 +870,37 @@ public final class AutoIngestManager extends Observable implements PropertyChang
}
/**
- * Sets the coordination service node data for an auto ingest job.
+ * Sets the coordination service manifest node.
*
- * Note that a new auto ingest node data object will be created from the job
- * passed in. Thus, if the data version of the node has changed, the node
- * will be "upgraded" as well as updated.
+ * Note that a new auto ingest job node data object will be created from the
+ * job passed in. Thus, if the data version of the node has changed, the
+ * node will be "upgraded" as well as updated.
*
* @param job The auto ingest job.
*/
- void updateCoordinationServiceNode(AutoIngestJob job) throws CoordinationServiceException, InterruptedException {
+ void updateCoordinationServiceManifestNode(AutoIngestJob job) throws CoordinationServiceException, InterruptedException {
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(job);
String manifestNodePath = job.getManifest().getFilePath().toString();
byte[] rawData = nodeData.toArray();
coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath, rawData);
}
+ /**
+ * Sets the error flag for case node data given a case directory path.
+ *
+ * @param caseDirectoryPath The case directory path.
+ *
+ * @throws CoordinationService.CoordinationServiceException
+ * @throws InterruptedException
+ * @throws CaseNodeData.InvalidDataException
+ */
+ private void setCaseNodeDataErrorsOccurred(Path caseDirectoryPath) throws CoordinationServiceException, InterruptedException, CaseNodeData.InvalidDataException {
+ CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString()));
+ caseNodeData.setErrorsOccurred(true);
+ byte[] rawData = caseNodeData.toArray();
+ coordinationService.setNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString(), rawData);
+ }
+
/**
* A task that submits an input directory scan task to the input directory
* scan task executor.
@@ -1041,8 +1062,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
if (null != manifest) {
/*
- * Update the mapping of case names to manifest paths that is
- * used for case deletion.
+ * Update the mapping of case names to manifest paths that
+ * is used for case deletion.
*/
String caseName = manifest.getCaseName();
Path manifestPath = manifest.getFilePath();
@@ -1056,8 +1077,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
}
/*
- * Add a job to the pending jobs queue, the completed jobs list,
- * or do crashed job recovery, as required.
+ * Add a job to the pending jobs queue, the completed jobs
+ * list, or do crashed job recovery, as required.
*/
try {
byte[] rawData = coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString());
@@ -1077,7 +1098,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
break;
case DELETED:
/*
- * Ignore jobs marked as "deleted."
+ * Ignore jobs marked as "deleted."
*/
break;
default:
@@ -1147,8 +1168,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
}
/*
- * Try to upgrade/update the coordination service node data for
- * the job.
+ * Try to upgrade/update the coordination service manifest node
+ * data for the job.
*
* An exclusive lock is obtained before doing so because another
* host may have already found the job, obtained an exclusive
@@ -1161,7 +1182,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
*/
try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) {
if (null != manifestLock) {
- updateCoordinationServiceNode(job);
+ updateCoordinationServiceManifestNode(job);
}
} catch (CoordinationServiceException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifest.getFilePath()), ex);
@@ -1186,9 +1207,9 @@ public final class AutoIngestManager extends Observable implements PropertyChang
*/
private void addNewPendingJob(Manifest manifest) throws InterruptedException, AutoIngestJobException {
/*
- * Create the coordination service node data for the job. Note that
- * getting the lock will create the node for the job (with no data)
- * if it does not already exist.
+ * Create the coordination service manifest node data for the job.
+ * Note that getting the lock will create the node for the job (with
+ * no data) if it does not already exist.
*
* An exclusive lock is obtained before creating the node data
* because another host may have already found the job, obtained an
@@ -1202,7 +1223,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) {
if (null != manifestLock) {
AutoIngestJob job = new AutoIngestJob(manifest);
- updateCoordinationServiceNode(job);
+ updateCoordinationServiceManifestNode(job);
newPendingJobsList.add(job);
}
} catch (CoordinationServiceException ex) {
@@ -1218,15 +1239,17 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* the node that was processing the job crashed and the processing
* status was not updated.
*
- * @param manifest The manifest for upgrading the node.
- * @param nodeData The node data.
+ * @param manifest The manifest for upgrading the node.
+ * @param jobNodeData The auto ingest job node data.
*
- * @throws InterruptedException if the thread running the input
- * directory scan task is interrupted while
- * blocked, i.e., if auto ingest is
- * shutting down.
+ * @throws InterruptedException if the thread running the input
+ * directory scan task is interrupted
+ * while blocked, i.e., if auto ingest is
+ * shutting down.
+ * @throws AutoIngestJobException if there is an issue creating a new
+ * AutoIngestJob object.
*/
- private void doRecoveryIfCrashed(Manifest manifest, AutoIngestJobNodeData nodeData) throws InterruptedException, AutoIngestJobException {
+ private void doRecoveryIfCrashed(Manifest manifest, AutoIngestJobNodeData jobNodeData) throws InterruptedException, AutoIngestJobException {
/*
* Try to get an exclusive lock on the coordination service node for
* the job. If the lock cannot be obtained, another host in the auto
@@ -1237,48 +1260,35 @@ public final class AutoIngestManager extends Observable implements PropertyChang
if (null != manifestLock) {
SYS_LOGGER.log(Level.SEVERE, "Attempting crash recovery for {0}", manifestPath);
try {
+ Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, manifest.getCaseName());
+
/*
* Create the recovery job.
*/
- AutoIngestJob job = new AutoIngestJob(nodeData);
+ AutoIngestJob job = new AutoIngestJob(jobNodeData);
int numberOfCrashes = job.getNumberOfCrashes();
- ++numberOfCrashes;
- job.setNumberOfCrashes(numberOfCrashes);
- job.setCompletedDate(new Date(0));
- Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, manifest.getCaseName());
+ if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) {
+ ++numberOfCrashes;
+ job.setNumberOfCrashes(numberOfCrashes);
+ if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) {
+ job.setCompletedDate(new Date(0));
+ } else {
+ job.setCompletedDate(Date.from(Instant.now()));
+ }
+ }
+
if (null != caseDirectoryPath) {
job.setCaseDirectoryPath(caseDirectoryPath);
job.setErrorsOccurred(true);
+ try {
+ setCaseNodeDataErrorsOccurred(caseDirectoryPath);
+ } catch (CaseNodeData.InvalidDataException ex) {
+ SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to get case node data for %s", caseDirectoryPath), ex);
+ }
} else {
job.setErrorsOccurred(false);
}
- /*
- * Update the coordination service node for the job. If
- * this fails, leave the recovery to another host.
- */
- try {
- updateCoordinationServiceNode(job);
- if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) {
- newPendingJobsList.add(job);
- } else {
- newCompletedJobsList.add(new AutoIngestJob(nodeData));
- }
- } catch (CoordinationServiceException ex) {
- SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifestPath), ex);
- return;
- }
-
- /*
- * Write the alert file and do the logging.
- */
- if (null != caseDirectoryPath) {
- try {
- AutoIngestAlertFile.create(nodeData.getCaseDirectoryPath());
- } catch (AutoIngestAlertFileException ex) {
- SYS_LOGGER.log(Level.SEVERE, String.format("Error creating alert file for crashed job for %s", manifestPath), ex);
- }
- }
if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) {
job.setProcessingStatus(AutoIngestJob.ProcessingStatus.PENDING);
if (null != caseDirectoryPath) {
@@ -1292,13 +1302,32 @@ public final class AutoIngestManager extends Observable implements PropertyChang
job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED);
if (null != caseDirectoryPath) {
try {
- new AutoIngestJobLogger(manifest.getFilePath(), manifest.getDataSourceFileName(), nodeData.getCaseDirectoryPath()).logCrashRecoveryNoRetry();
+ new AutoIngestJobLogger(manifest.getFilePath(), manifest.getDataSourceFileName(), caseDirectoryPath).logCrashRecoveryNoRetry();
} catch (AutoIngestJobLoggerException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error creating case auto ingest log entry for crashed job for %s", manifestPath), ex);
}
}
}
+ /*
+ * Update the coordination service node for the job. If
+ * this fails, leave the recovery to another host.
+ */
+ try {
+ updateCoordinationServiceManifestNode(job);
+ } catch (CoordinationServiceException ex) {
+ SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifestPath), ex);
+ return;
+ }
+
+ jobNodeData = new AutoIngestJobNodeData(job);
+
+ if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) {
+ newPendingJobsList.add(job);
+ } else {
+ newCompletedJobsList.add(new AutoIngestJob(jobNodeData));
+ }
+
} finally {
try {
manifestLock.release();
@@ -1352,15 +1381,15 @@ public final class AutoIngestManager extends Observable implements PropertyChang
job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED);
/*
- * Try to upgrade/update the coordination service node data
- * for the job. It is possible that two hosts will both try
- * to obtain the lock to do the upgrade operation at the
- * same time. If this happens, the host that is holding the
- * lock will complete the upgrade operation.
+ * Try to upgrade/update the coordination service manifest
+ * node data for the job. It is possible that two hosts will
+ * both try to obtain the lock to do the upgrade operation
+ * at the same time. If this happens, the host that is
+ * holding the lock will complete the upgrade operation.
*/
try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) {
if (null != manifestLock) {
- updateCoordinationServiceNode(job);
+ updateCoordinationServiceManifestNode(job);
}
} catch (CoordinationServiceException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifest.getFilePath()), ex);
@@ -1507,8 +1536,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
errorState = ErrorState.ANALYSIS_STARTUP_ERROR;
} else if (ex instanceof FileExportException) {
errorState = ErrorState.FILE_EXPORT_ERROR;
- } else if (ex instanceof AutoIngestAlertFileException) {
- errorState = ErrorState.ALERT_FILE_ERROR;
} else if (ex instanceof AutoIngestJobLoggerException) {
errorState = ErrorState.JOB_LOGGER_ERROR;
} else if (ex instanceof AutoIngestDataSourceProcessorException) {
@@ -1691,9 +1718,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* @throws FileExportException if there is an
* error exporting
* files.
- * @throws AutoIngestAlertFileException if there is an
- * error creating an
- * alert file.
* @throws AutoIngestJobLoggerException if there is an
* error writing to
* the auto ingest
@@ -1710,7 +1734,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* auto ingest node
* data objects.
*/
- private void processJobs() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, AutoIngestJobNodeData.InvalidDataException {
+ private void processJobs() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, AutoIngestJobNodeData.InvalidDataException, CaseNodeData.InvalidDataException {
SYS_LOGGER.log(Level.INFO, "Started processing pending jobs queue");
Lock manifestLock = JobProcessingTask.this.dequeueAndLockNextJob();
while (null != manifestLock) {
@@ -1890,9 +1914,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* @throws FileExportException if there is an
* error exporting
* files.
- * @throws AutoIngestAlertFileException if there is an
- * error creating an
- * alert file.
* @throws AutoIngestJobLoggerException if there is an
* error writing to
* the auto ingest
@@ -1909,13 +1930,13 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* auto ingest node
* data objects.
*/
- private void processJob() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, AutoIngestJobNodeData.InvalidDataException {
+ private void processJob() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, CaseNodeData.InvalidDataException {
Path manifestPath = currentJob.getManifest().getFilePath();
SYS_LOGGER.log(Level.INFO, "Started processing of {0}", manifestPath);
currentJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.PROCESSING);
currentJob.setProcessingStage(AutoIngestJob.Stage.STARTING, Date.from(Instant.now()));
currentJob.setProcessingHostName(AutoIngestManager.LOCAL_HOST_NAME);
- updateCoordinationServiceNode(currentJob);
+ updateCoordinationServiceManifestNode(currentJob);
setChanged();
notifyObservers(Event.JOB_STARTED);
eventPublisher.publishRemotely(new AutoIngestJobStartedEvent(currentJob));
@@ -1939,14 +1960,14 @@ public final class AutoIngestManager extends Observable implements PropertyChang
currentJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.PENDING);
}
currentJob.setProcessingHostName("");
- updateCoordinationServiceNode(currentJob);
+ updateCoordinationServiceManifestNode(currentJob);
boolean retry = (!currentJob.isCanceled() && !currentJob.isCompleted());
SYS_LOGGER.log(Level.INFO, "Completed processing of {0}, retry = {1}", new Object[]{manifestPath, retry});
if (currentJob.isCanceled()) {
Path caseDirectoryPath = currentJob.getCaseDirectoryPath();
if (null != caseDirectoryPath) {
- AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
+ setCaseNodeDataErrorsOccurred(caseDirectoryPath);
AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, currentJob.getManifest().getDataSourceFileName(), caseDirectoryPath);
jobLogger.logJobCancelled();
}
@@ -1994,7 +2015,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* i.e., if auto ingest is
* shutting down.
*/
- private void attemptJob() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException {
+ private void attemptJob() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, CaseNodeData.InvalidDataException {
updateConfiguration();
if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) {
return;
@@ -2115,7 +2136,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
Case.openAsCurrentCase(metadataFilePath.toString());
} else {
caseDirectoryPath = PathUtils.createCaseFolderPath(rootOutputDirectory, caseName);
- Case.createAsCurrentCase(caseDirectoryPath.toString(), caseName, "", "", CaseType.MULTI_USER_CASE);
+ CaseDetails caseDetails = new CaseDetails(caseName);
+ Case.createAsCurrentCase(CaseType.MULTI_USER_CASE, caseDirectoryPath.toString(), caseDetails);
/*
* Sleep a bit before releasing the lock to ensure
* that the new case folder is visible on the
@@ -2158,8 +2180,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* level ingest modules.
* @throws FileExportException if there is an error exporting
* files.
- * @throws AutoIngestAlertFileException if there is an error creating an
- * alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the
* case.
@@ -2168,7 +2188,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto
* ingest is shutting down.
*/
- private void runIngestForJob(Case caseForJob) throws CoordinationServiceException, AnalysisStartupException, FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException {
+ private void runIngestForJob(Case caseForJob) throws CoordinationServiceException, AnalysisStartupException, FileExportException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, CaseNodeData.InvalidDataException {
try {
if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) {
return;
@@ -2196,8 +2216,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* level ingest modules.
* @throws FileExportException if there is an error exporting
* files.
- * @throws AutoIngestAlertFileException if there is an error creating an
- * alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the
* case.
@@ -2206,12 +2224,12 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto
* ingest is shutting down.
*/
- private void ingestDataSource(Case caseForJob) throws AnalysisStartupException, FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException {
+ private void ingestDataSource(Case caseForJob) throws AnalysisStartupException, FileExportException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, CaseNodeData.InvalidDataException, CoordinationServiceException {
if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) {
return;
}
- DataSource dataSource = identifyDataSource();
+ AutoIngestDataSource dataSource = identifyDataSource();
if (null == dataSource) {
currentJob.setProcessingStage(AutoIngestJob.Stage.COMPLETED, Date.from(Instant.now()));
return;
@@ -2254,8 +2272,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
*
* @return A data source object.
*
- * @throws AutoIngestAlertFileException if there is an error creating an
- * alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the
* case.
@@ -2264,7 +2280,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* interrupted while blocked, i.e.,
* if auto ingest is shutting down.
*/
- private DataSource identifyDataSource() throws AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException {
+ private AutoIngestDataSource identifyDataSource() throws AutoIngestJobLoggerException, InterruptedException, CaseNodeData.InvalidDataException, CoordinationServiceException {
Manifest manifest = currentJob.getManifest();
Path manifestPath = manifest.getFilePath();
SYS_LOGGER.log(Level.INFO, "Identifying data source for {0} ", manifestPath);
@@ -2276,22 +2292,20 @@ public final class AutoIngestManager extends Observable implements PropertyChang
if (!dataSource.exists()) {
SYS_LOGGER.log(Level.SEVERE, "Missing data source for {0}", manifestPath);
currentJob.setErrorsOccurred(true);
- AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
+ setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logMissingDataSource();
return null;
}
String deviceId = manifest.getDeviceId();
- return new DataSource(deviceId, dataSourcePath);
+ return new AutoIngestDataSource(deviceId, dataSourcePath);
}
-
+
/**
* Passes the data source for the current job through a data source
* processor that adds it to the case database.
*
* @param dataSource The data source.
*
- * @throws AutoIngestAlertFileException if there is an error creating an
- * alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the
* case.
@@ -2300,23 +2314,20 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto
* ingest is shutting down.
*/
- private void runDataSourceProcessor(Case caseForJob, DataSource dataSource) throws InterruptedException, AutoIngestAlertFileException, AutoIngestJobLoggerException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException {
+ private void runDataSourceProcessor(Case caseForJob, AutoIngestDataSource dataSource) throws InterruptedException, AutoIngestJobLoggerException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, CaseNodeData.InvalidDataException, CoordinationServiceException {
Manifest manifest = currentJob.getManifest();
Path manifestPath = manifest.getFilePath();
SYS_LOGGER.log(Level.INFO, "Adding data source for {0} ", manifestPath);
currentJob.setProcessingStage(AutoIngestJob.Stage.ADDING_DATA_SOURCE, Date.from(Instant.now()));
- UUID taskId = UUID.randomUUID();
- DataSourceProcessorCallback callBack = new AddDataSourceCallback(caseForJob, dataSource, taskId, ingestLock);
DataSourceProcessorProgressMonitor progressMonitor = new DoNothingDSPProgressMonitor();
Path caseDirectoryPath = currentJob.getCaseDirectoryPath();
AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, manifest.getDataSourceFileName(), caseDirectoryPath);
try {
- caseForJob.notifyAddingDataSource(taskId);
- Map validDataSourceProcessorsMap;
+ // Get an ordered list of data source processors to try
+ List validDataSourceProcessors;
try {
- // lookup all AutomatedIngestDataSourceProcessors and poll which ones are able to process the current data source
- validDataSourceProcessorsMap = DataSourceProcessorUtility.getDataSourceProcessor(dataSource.getPath());
+ validDataSourceProcessors = DataSourceProcessorUtility.getOrderedListOfDataSourceProcessors(dataSource.getPath());
} catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) {
SYS_LOGGER.log(Level.SEVERE, "Exception while determining best data source processor for {0}", dataSource.getPath());
// rethrow the exception. It will get caught & handled upstream and will result in AIM auto-pause.
@@ -2324,24 +2335,22 @@ public final class AutoIngestManager extends Observable implements PropertyChang
}
// did we find a data source processor that can process the data source
- if (validDataSourceProcessorsMap.isEmpty()) {
+ if (validDataSourceProcessors.isEmpty()) {
// This should never happen. We should add all unsupported data sources as logical files.
- AutoIngestAlertFile.create(caseDirectoryPath);
+ setCaseNodeDataErrorsOccurred(caseDirectoryPath);
currentJob.setErrorsOccurred(true);
jobLogger.logFailedToIdentifyDataSource();
SYS_LOGGER.log(Level.WARNING, "Unsupported data source {0} for {1}", new Object[]{dataSource.getPath(), manifestPath}); // NON-NLS
return;
}
- // Get an ordered list of data source processors to try
- List validDataSourceProcessors = validDataSourceProcessorsMap.entrySet().stream()
- .sorted(Map.Entry.comparingByValue().reversed())
- .map(Map.Entry::getKey)
- .collect(Collectors.toList());
-
synchronized (ingestLock) {
// Try each DSP in decreasing order of confidence
for (AutoIngestDataSourceProcessor selectedProcessor : validDataSourceProcessors) {
+ UUID taskId = UUID.randomUUID();
+ caseForJob.notifyAddingDataSource(taskId);
+ DataSourceProcessorCallback callBack = new AddDataSourceCallback(caseForJob, dataSource, taskId, ingestLock);
+ caseForJob.notifyAddingDataSource(taskId);
jobLogger.logDataSourceProcessorSelected(selectedProcessor.getDataSourceType());
SYS_LOGGER.log(Level.INFO, "Identified data source type for {0} as {1}", new Object[]{manifestPath, selectedProcessor.getDataSourceType()});
try {
@@ -2352,7 +2361,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
// Log that the current DSP failed and set the error flag. We consider it an error
// if a DSP fails even if a later one succeeds since we expected to be able to process
// the data source which each DSP on the list.
- AutoIngestAlertFile.create(caseDirectoryPath);
+ setCaseNodeDataErrorsOccurred(caseDirectoryPath);
currentJob.setErrorsOccurred(true);
jobLogger.logDataSourceProcessorError(selectedProcessor.getDataSourceType());
SYS_LOGGER.log(Level.SEVERE, "Exception while processing {0} with data source processor {1}", new Object[]{dataSource.getPath(), selectedProcessor.getDataSourceType()});
@@ -2376,8 +2385,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
*
* @param dataSource The data source.
*
- * @throws AutoIngestAlertFileException if there is an error creating an
- * alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the
* case.
@@ -2386,7 +2393,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto
* ingest is shutting down.
*/
- private void logDataSourceProcessorResult(DataSource dataSource) throws AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException {
+ private void logDataSourceProcessorResult(AutoIngestDataSource dataSource) throws AutoIngestJobLoggerException, InterruptedException, CaseNodeData.InvalidDataException, CoordinationServiceException {
Manifest manifest = currentJob.getManifest();
Path manifestPath = manifest.getFilePath();
Path caseDirectoryPath = currentJob.getCaseDirectoryPath();
@@ -2398,7 +2405,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
jobLogger.logDataSourceAdded();
if (dataSource.getContent().isEmpty()) {
currentJob.setErrorsOccurred(true);
- AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
+ setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logNoDataSourceContent();
}
break;
@@ -2410,7 +2417,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
jobLogger.logDataSourceAdded();
if (dataSource.getContent().isEmpty()) {
currentJob.setErrorsOccurred(true);
- AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
+ setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logNoDataSourceContent();
}
break;
@@ -2420,7 +2427,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
SYS_LOGGER.log(Level.SEVERE, "Critical error running data source processor for {0}: {1}", new Object[]{manifestPath, errorMessage});
}
currentJob.setErrorsOccurred(true);
- AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
+ setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logFailedToAddDataSource();
break;
}
@@ -2434,7 +2441,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
*/
SYS_LOGGER.log(Level.WARNING, "Cancellation while waiting for data source processor for {0}", manifestPath);
currentJob.setErrorsOccurred(true);
- AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
+ setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logDataSourceProcessorCancelled();
}
}
@@ -2448,8 +2455,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
*
* @throws AnalysisStartupException if there is an error analyzing
* the data source.
- * @throws AutoIngestAlertFileException if there is an error creating an
- * alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the
* case.
@@ -2458,7 +2463,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto
* ingest is shutting down.
*/
- private void analyze(DataSource dataSource) throws AnalysisStartupException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException {
+ private void analyze(AutoIngestDataSource dataSource) throws AnalysisStartupException, AutoIngestJobLoggerException, InterruptedException, CaseNodeData.InvalidDataException, CoordinationServiceException {
Manifest manifest = currentJob.getManifest();
Path manifestPath = manifest.getFilePath();
SYS_LOGGER.log(Level.INFO, "Starting ingest modules analysis for {0} ", manifestPath);
@@ -2490,7 +2495,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
if (!cancelledModules.isEmpty()) {
SYS_LOGGER.log(Level.WARNING, String.format("Ingest module(s) cancelled for %s", manifestPath));
currentJob.setErrorsOccurred(true);
- AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
+ setCaseNodeDataErrorsOccurred(caseDirectoryPath);
for (String module : snapshot.getCancelledDataSourceIngestModules()) {
SYS_LOGGER.log(Level.WARNING, String.format("%s ingest module cancelled for %s", module, manifestPath));
jobLogger.logIngestModuleCancelled(module);
@@ -2500,7 +2505,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} else {
currentJob.setProcessingStage(AutoIngestJob.Stage.CANCELLING, Date.from(Instant.now()));
currentJob.setErrorsOccurred(true);
- AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
+ setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logAnalysisCancelled();
CancellationReason cancellationReason = snapshot.getCancellationReason();
if (CancellationReason.NOT_CANCELLED != cancellationReason && CancellationReason.USER_CANCELLED != cancellationReason) {
@@ -2513,13 +2518,13 @@ public final class AutoIngestManager extends Observable implements PropertyChang
SYS_LOGGER.log(Level.SEVERE, String.format("%s ingest module startup error for %s", error.getModuleDisplayName(), manifestPath), error.getThrowable());
}
currentJob.setErrorsOccurred(true);
- AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
+ setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logIngestModuleStartupErrors();
throw new AnalysisStartupException(String.format("Error(s) during ingest module startup for %s", manifestPath));
} else {
SYS_LOGGER.log(Level.SEVERE, String.format("Ingest manager ingest job start error for %s", manifestPath), ingestJobStartResult.getStartupException());
currentJob.setErrorsOccurred(true);
- AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
+ setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logAnalysisStartupError();
throw new AnalysisStartupException("Ingest manager error starting job", ingestJobStartResult.getStartupException());
}
@@ -2528,7 +2533,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
SYS_LOGGER.log(Level.SEVERE, "Ingest job settings error for {0}: {1}", new Object[]{manifestPath, warning});
}
currentJob.setErrorsOccurred(true);
- AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
+ setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logIngestJobSettingsErrors();
throw new AnalysisStartupException("Error(s) in ingest job settings");
}
@@ -2547,8 +2552,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
*
* @throws FileExportException if there is an error exporting
* the files.
- * @throws AutoIngestAlertFileException if there is an error creating an
- * alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the
* case.
@@ -2557,7 +2560,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto
* ingest is shutting down.
*/
- private void exportFiles(DataSource dataSource) throws FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException {
+ private void exportFiles(AutoIngestDataSource dataSource) throws FileExportException, AutoIngestJobLoggerException, InterruptedException, CaseNodeData.InvalidDataException, CoordinationServiceException {
Manifest manifest = currentJob.getManifest();
Path manifestPath = manifest.getFilePath();
SYS_LOGGER.log(Level.INFO, "Exporting files for {0}", manifestPath);
@@ -2573,11 +2576,11 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} catch (FileExportException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error doing file export for %s", manifestPath), ex);
currentJob.setErrorsOccurred(true);
- AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
+ setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logFileExportError();
}
}
-
+
/**
* A data source processor progress monitor does nothing. There is
* currently no mechanism for showing or recording data source processor
@@ -2739,7 +2742,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
currentJob.getProcessingStageDetails();
setChanged();
notifyObservers(Event.JOB_STATUS_UPDATED);
- updateCoordinationServiceNode(currentJob);
+ updateCoordinationServiceManifestNode(currentJob);
eventPublisher.publishRemotely(new AutoIngestJobStatusEvent(currentJob));
}
@@ -2842,7 +2845,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
CASE_MANAGEMENT_ERROR("Case management error"),
ANALYSIS_STARTUP_ERROR("Analysis startup error"),
FILE_EXPORT_ERROR("File export error"),
- ALERT_FILE_ERROR("Alert file error"),
JOB_LOGGER_ERROR("Job logger error"),
DATA_SOURCE_PROCESSOR_ERROR("Data source processor error"),
UNEXPECTED_EXCEPTION("Unknown error");
@@ -2917,7 +2919,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
PARTIALLY_DELETED,
FULLY_DELETED
}
-
+
static final class AutoIngestManagerException extends Exception {
private static final long serialVersionUID = 1L;
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsCollector.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsCollector.java
new file mode 100755
index 0000000000..9567b70470
--- /dev/null
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsCollector.java
@@ -0,0 +1,160 @@
+/*
+ * 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.List;
+import java.util.logging.Level;
+import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
+import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
+import org.sleuthkit.autopsy.coreutils.Logger;
+
+/**
+ * Collects metrics for an auto ingest cluster.
+ */
+final class AutoIngestMetricsCollector {
+
+ private static final Logger LOGGER = Logger.getLogger(AutoIngestMetricsCollector.class.getName());
+ private CoordinationService coordinationService;
+
+ /**
+ * Creates an instance of the AutoIngestMetricsCollector.
+ *
+ * @throws AutoIngestMetricsCollector.AutoIngestMetricsCollectorException
+ */
+ AutoIngestMetricsCollector() throws AutoIngestMetricsCollectorException {
+ try {
+ coordinationService = CoordinationService.getInstance();
+ } catch (CoordinationServiceException ex) {
+ throw new AutoIngestMetricsCollectorException("Failed to get coordination service", ex); //NON-NLS
+ }
+ }
+
+ /**
+ * Gets a new metrics snapshot from the coordination service for an auto
+ * ingest cluster.
+ *
+ * @return The metrics snapshot.
+ */
+ MetricsSnapshot queryCoordinationServiceForMetrics() {
+ try {
+ MetricsSnapshot newMetricsSnapshot = new MetricsSnapshot();
+ List nodeList = coordinationService.getNodeList(CoordinationService.CategoryNode.MANIFESTS);
+ for (String node : nodeList) {
+ try {
+ AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, node));
+ if (nodeData.getVersion() < 1) {
+ /*
+ * Ignore version '0' nodes that have not been
+ * "upgraded" since they don't carry enough data.
+ */
+ continue;
+ }
+ AutoIngestJob job = new AutoIngestJob(nodeData);
+ AutoIngestJob.ProcessingStatus processingStatus = nodeData.getProcessingStatus();
+ switch (processingStatus) {
+ case PENDING:
+ case PROCESSING:
+ case DELETED:
+ /*
+ * These are not jobs we care about for metrics, so
+ * we will ignore them.
+ */
+ break;
+ case COMPLETED:
+ newMetricsSnapshot.addCompletedJobDate(job.getCompletedDate());
+ break;
+ default:
+ LOGGER.log(Level.SEVERE, "Unknown AutoIngestJobData.ProcessingStatus");
+ break;
+ }
+ } catch (InterruptedException ex) {
+ LOGGER.log(Level.SEVERE, String.format("Unexpected interrupt while retrieving coordination service node data for '%s'", node), ex);
+ } catch (AutoIngestJobNodeData.InvalidDataException ex) {
+ LOGGER.log(Level.SEVERE, String.format("Unable to use node data for '%s'", node), ex);
+ } catch (AutoIngestJob.AutoIngestJobException ex) {
+ LOGGER.log(Level.SEVERE, String.format("Failed to create a job for '%s'", node), ex);
+ }
+ }
+
+ return newMetricsSnapshot;
+
+ } catch (CoordinationService.CoordinationServiceException ex) {
+ LOGGER.log(Level.SEVERE, "Failed to get node list from coordination service", ex);
+ return new MetricsSnapshot();
+ }
+ }
+
+ /**
+ * A snapshot of metrics for an auto ingest cluster.
+ */
+ static final class MetricsSnapshot {
+
+ private final List 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(java.util.Date date) {
+ completedJobDates.add(date.getTime());
+ }
+ }
+
+ /**
+ * Exception type thrown when there is an error completing an auto ingest
+ * metrics collector operation.
+ */
+ static final class AutoIngestMetricsCollectorException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructs an instance of the exception type thrown when there is an
+ * error completing an auto ingest metrics collector operation.
+ *
+ * @param message The exception message.
+ */
+ private AutoIngestMetricsCollectorException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs an instance of the exception type thrown when there is an
+ * error completing an auto ingest metrics collector operation.
+ *
+ * @param message The exception message.
+ * @param cause A Throwable cause for the error.
+ */
+ private AutoIngestMetricsCollectorException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ }
+}
\ No newline at end of file
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..80bcb6958b
--- /dev/null
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.java
@@ -0,0 +1,212 @@
+/*
+ * 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;
+
+/**
+ * Displays auto ingest metrics for a cluster.
+ */
+final class AutoIngestMetricsDialog extends javax.swing.JDialog {
+
+ private final AutoIngestMetricsCollector autoIngestMetricsCollector;
+
+ /**
+ * Creates an instance of AutoIngestMetricsDialog
+ *
+ * @param parent The parent container.
+ */
+ @Messages({
+ "AutoIngestMetricsDialog.title.text=Auto Ingest Cluster Metrics",
+ "AutoIngestMetricsDialog.initReportText=Select a date below and click the 'Get Metrics Since...' button to generate\na metrics report."
+ })
+ AutoIngestMetricsDialog(Container parent) throws AutoIngestMetricsDialogException {
+ super((Window) parent, NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.title.text"), ModalityType.MODELESS);
+ try {
+ autoIngestMetricsCollector = new AutoIngestMetricsCollector();
+ } catch (AutoIngestMetricsCollector.AutoIngestMetricsCollectorException ex) {
+ throw new AutoIngestMetricsDialogException("Error starting up the auto ingest metrics dialog.", ex);
+ }
+ initComponents();
+ reportTextArea.setText(NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.initReportText"));
+ setModal(true);
+ setSize(getPreferredSize());
+ setLocationRelativeTo(parent);
+ setVisible(true);
+ }
+
+ /**
+ * Update the metrics shown in the report text area.
+ */
+ private void updateMetrics() {
+ if(datePicker.getDate() == null) {
+ return;
+ }
+
+ AutoIngestMetricsCollector.MetricsSnapshot metricsSnapshot = autoIngestMetricsCollector.queryCoordinationServiceForMetrics();
+ Object[] completedJobDates = metricsSnapshot.getCompletedJobDates().toArray();
+ int count = 0;
+ long pickedDate = datePicker.getDate().atStartOfDay().toEpochSecond(ZoneOffset.UTC) * 1000;
+ for(int i = completedJobDates.length - 1; i >= 0; i--) {
+ if((Long)completedJobDates[i] >= pickedDate) {
+ count++;
+ }
+ }
+
+ SimpleDateFormat dateFormatter = new SimpleDateFormat("MMM d, yyyy");
+ reportTextArea.setText(String.format(
+ "Since %s:\n" +
+ "\tNumber of Jobs Completed: %d\n",
+ dateFormatter.format(Date.valueOf(datePicker.getDate())),
+ count
+ ));
+ }
+
+ /**
+ * Exception type thrown when there is an error completing an auto ingest
+ * metrics dialog operation.
+ */
+ static final class AutoIngestMetricsDialogException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructs an instance of the exception type thrown when there is an
+ * error completing an auto ingest metrics dialog operation.
+ *
+ * @param message The exception message.
+ */
+ private AutoIngestMetricsDialogException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs an instance of the exception type thrown when there is an
+ * error completing an auto ingest metrics dialog operation.
+ *
+ * @param message The exception message.
+ * @param cause A Throwable cause for the error.
+ */
+ private AutoIngestMetricsDialogException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //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
+}
\ No newline at end of file
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java
index 9a262bb6d3..e46a5e43c0 100755
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java
@@ -43,7 +43,7 @@ import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJob.ProcessingSta
* An auto ingest monitor responsible for monitoring and reporting the
* processing of auto ingest jobs.
*/
-public final class AutoIngestMonitor extends Observable implements PropertyChangeListener {
+final class AutoIngestMonitor extends Observable implements PropertyChangeListener {
private static final Logger LOGGER = Logger.getLogger(AutoIngestMonitor.class.getName());
private static final int NUM_COORD_SVC_QUERY_THREADS = 1;
@@ -265,11 +265,15 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang
}
} catch (InterruptedException ex) {
LOGGER.log(Level.SEVERE, String.format("Unexpected interrupt while retrieving coordination service node data for '%s'", node), ex);
- } catch (AutoIngestJobNodeData.InvalidDataException | AutoIngestJob.AutoIngestJobException ex) {
+ } catch (AutoIngestJobNodeData.InvalidDataException ex) {
LOGGER.log(Level.SEVERE, String.format("Unable to use node data for '%s'", node), ex);
+ } catch (AutoIngestJob.AutoIngestJobException ex) {
+ LOGGER.log(Level.SEVERE, String.format("Failed to create a job for '%s'", node), ex);
}
}
+
return newJobsSnapshot;
+
} catch (CoordinationServiceException ex) {
LOGGER.log(Level.SEVERE, "Failed to get node list from coordination service", ex);
return new JobsSnapshot();
@@ -552,4 +556,4 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang
}
}
-}
+}
\ No newline at end of file
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..31ecd5f4ca
--- /dev/null
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestRowSorter.java
@@ -0,0 +1,57 @@
+/*
+ * 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
+ */
+class AutoIngestRowSorter extends TableRowSorter {
+
+ AutoIngestRowSorter(M tModel) {
+ super(tModel);
+ }
+
+ @Override
+ public void toggleSortOrder(int column) {
+ if (!this.getModel().getColumnClass(column).equals(Date.class) && !this.getModel().getColumnClass(column).equals(Integer.class)) {
+ //currently the only Integer column this sorter is being applied to is the Priority column
+ super.toggleSortOrder(column); //if it isn't a date or Integer column perform the regular sorting
+ } else {
+ ArrayList 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/Bundle.properties b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties
index edac418672..5f335b1ba4 100755
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties
@@ -1,4 +1,3 @@
-CTL_OpenAction=Open Case...
AutoIngestDashboard.lbCompleted.text=Completed Jobs
AutoIngestDashboard.lbRunning.text=Running Jobs
AutoIngestDashboard.lbPending.text=Pending Jobs
@@ -47,14 +46,10 @@ OpenIDE-Module-Long-Description=\
We make no guarantee that the API of this module will not change, so developers should be careful when relying on it.
OpenIDE-Module-Name=Experimental
OpenIDE-Module-Short-Description=This module contains features that are being developed by Basis Technology and are not part of the default Autopsy distribution.
-ReviewModeCasePanel.cannotOpenCase=Cannot Open Case
-ReviewModeCasePanel.casePathNotFound=Case path not found
-ReviewModeCasePanel.caseIsLocked=Single-user case is locked.
DisplayLogDialog.cannotOpenLog=Unable to open the selected case log file
DisplayLogDialog.cannotFindLog=Unable to find the selected case log file
DisplayLogDialog.unableToShowLogFile=Unable to show log file
DisplayLogDialog.okay=Okay
-ReviewModeCasePanel.bnShowLog.text=&Show Log
CopyFilesPanel.lbFrom.text=From Source
CopyFilesPanel.lbTo.text=Destination Case
CopyFilesPanel.bnCopy.text=&Copy
@@ -128,8 +123,6 @@ CopyFilesPanel.cbThrottleNetwork.toolTipText=Select this box if a low-band
CopyFilesPanel.bnShowCurrentLog.text=Show &Log
CopyFilesPanel.bnShowCurrentLog.text=Show &Log
CopyFilesPanel.lbCaseName.text=Case Name
-CaseStatusIconCellRenderer.tooltiptext.ok=Images processed successfully
-CaseStatusIconCellRenderer.tooltiptext.warning=An error occurred or processing was canceled for at least one image - please check the log
OptionsCategory_Name_Case_Import=Case Import
OptionsCategory_Keywords_Case_Import=Case Import Settings
CaseImportPanel.validationErrMsg.MUdisabled=Multi user settings must be enabled and saved
@@ -165,11 +158,6 @@ SingleUserCaseImporter.FailedToComplete=Failed to complete processing of
SingleUserCaseImporter.CompletedBatch=Completed batch processing of
SingleUserCaseImporter.AbortingBatch=Aborting batch processing of
SingleUserCaseImporter.SourceImageMissing=. Source image missing for
-ReviewModeCasePanel.CaseHeaderText=Case
-ReviewModeCasePanel.CreatedTimeHeaderText=Created Time
-ReviewModeCasePanel.StatusIconHeaderText=Status
-ReviewModeCasePanel.OutputFolderHeaderText=Output Folder
-ReviewModeCasePanel.LastAccessedTimeHeaderText=Last Accessed Time
CopyFilesPanel.bnOptions.text=&Options
AutoIngestDashboard.lbServicesStatus.text=Services Status:
AutoIngestDashboard.tbServicesStatusMessage.text=Connecting...
@@ -231,15 +219,6 @@ FileExporterSettingsPanel.BrowseReportTooltip_1=Browse for the Reports Folder
FileExporterSettingsPanel.NewRuleTooltip_1=Clear the rule editor to begin a new rule
FileExporterSettingsPanel.DeleteTooltip_1=Delete the selected rule
FileExporterSettingsPanel.SaveTooltip_1=Save the current rule
-AutoIngestCasePanel.rbDays.text=Days
-AutoIngestCasePanel.rbWeeks.text=Weeks
-AutoIngestCasePanel.rbMonths.text=Months
-AutoIngestCasePanel.rbAllCases.text=Everything
-AutoIngestCasePanel.bnRefresh.text=&Refresh
-AutoIngestCasePanel.bnOpen.text=&Open
-AutoIngestCasePanel.bnShowLog.toolTipText=Display case log file for selected case
-AutoIngestCasePanel.bnShowLog.text=&Show Log
-AutoIngestCasePanel.rbGroupLabel.text=Show cases accessed in the last 10:
AutoIngestDashboard.refreshButton.toolTipText=Refresh displayed tables
AutoIngestDashboard.refreshButton.text=&Refresh
AutoIngestDashboard.jButton1.text=jButton1
@@ -247,6 +226,11 @@ AutoIngestDashboard.prioritizeJobButton.toolTipText=Move the selected job to the
AutoIngestDashboard.prioritizeJobButton.text=Prioritize &Job
AutoIngestDashboard.prioritizeCaseButton.toolTipText=Move all images associated with a case to top of Pending queue.
AutoIngestDashboard.prioritizeCaseButton.text=Prioritize &Case
+AutoIngestMetricsDialog.reportTextArea.text=
+AutoIngestDashboard.clusterMetricsButton.text=Cluster Metrics
+AutoIngestMetricsDialog.metricsButton.text=Get Metrics Since...
+AutoIngestMetricsDialog.closeButton.text=Close
+AutoIngestMetricsDialog.datePicker.toolTipText=Choose a date
ArchiveFilePanel.pathLabel.text=Browse for an archive file:
ArchiveFilePanel.browseButton.text=Browse
ArchiveFilePanel.pathTextField.text=
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/DataSourceProcessorUtility.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/DataSourceProcessorUtility.java
index 6f88d70a28..4878f7fa7d 100755
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/DataSourceProcessorUtility.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/DataSourceProcessorUtility.java
@@ -21,7 +21,9 @@ package org.sleuthkit.autopsy.experimental.autoingest;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
import org.openide.util.Lookup;
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException;
@@ -30,8 +32,8 @@ import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.
* A utility class to find Data Source Processors
*/
class DataSourceProcessorUtility {
-
- private DataSourceProcessorUtility() {
+
+ private DataSourceProcessorUtility() {
}
/**
@@ -45,11 +47,7 @@ class DataSourceProcessorUtility {
* @throws
* org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
*/
- static Map getDataSourceProcessor(Path dataSourcePath) throws AutoIngestDataSourceProcessorException {
-
- // lookup all AutomatedIngestDataSourceProcessors
- Collection extends AutoIngestDataSourceProcessor> processorCandidates = Lookup.getDefault().lookupAll(AutoIngestDataSourceProcessor.class);
-
+ static Map getDataSourceProcessorForFile(Path dataSourcePath, Collection extends AutoIngestDataSourceProcessor> processorCandidates) throws AutoIngestDataSourceProcessorException {
Map validDataSourceProcessorsMap = new HashMap<>();
for (AutoIngestDataSourceProcessor processor : processorCandidates) {
int confidence = processor.canProcess(dataSourcePath);
@@ -60,4 +58,64 @@ class DataSourceProcessorUtility {
return validDataSourceProcessorsMap;
}
+
+ /**
+ * A utility method to find all Data Source Processors (DSP) that are able
+ * to process the input data source. Only the DSPs that implement
+ * AutoIngestDataSourceProcessor interface are used. Returns ordered list of
+ * data source processors. DSPs are ordered in descending order from highest
+ * confidence to lowest.
+ *
+ * @param dataSourcePath Full path to the data source
+ *
+ * @return Ordered list of data source processors. DSPs are ordered in
+ * descending order from highest confidence to lowest.
+ *
+ * @throws
+ * org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
+ */
+ static List getOrderedListOfDataSourceProcessors(Path dataSourcePath) throws AutoIngestDataSourceProcessorException {
+ // lookup all AutomatedIngestDataSourceProcessors
+ Collection extends AutoIngestDataSourceProcessor> processorCandidates = Lookup.getDefault().lookupAll(AutoIngestDataSourceProcessor.class);
+ return getOrderedListOfDataSourceProcessors(dataSourcePath, processorCandidates);
+ }
+
+ /**
+ * A utility method to find all Data Source Processors (DSP) that are able
+ * to process the input data source. Only the DSPs that implement
+ * AutoIngestDataSourceProcessor interface are used. Returns ordered list of
+ * data source processors. DSPs are ordered in descending order from highest
+ * confidence to lowest.
+ *
+ * @param dataSourcePath Full path to the data source
+ * @param processorCandidates Collection of AutoIngestDataSourceProcessor objects to use
+ *
+ * @return Ordered list of data source processors. DSPs are ordered in
+ * descending order from highest confidence to lowest.
+ *
+ * @throws
+ * org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
+ */
+ static List getOrderedListOfDataSourceProcessors(Path dataSourcePath, Collection extends AutoIngestDataSourceProcessor> processorCandidates) throws AutoIngestDataSourceProcessorException {
+ Map validDataSourceProcessorsMap = getDataSourceProcessorForFile(dataSourcePath, processorCandidates);
+ return orderDataSourceProcessorsByConfidence(validDataSourceProcessorsMap);
+ }
+
+
+ /**
+ * A utility method to get an ordered list of data source processors. DSPs
+ * are ordered in descending order from highest confidence to lowest.
+ *
+ * @param validDataSourceProcessorsMap Hash map of all DSPs that can process
+ * the data source along with their confidence score
+ * @return Ordered list of data source processors
+ */
+ static List orderDataSourceProcessorsByConfidence(Map validDataSourceProcessorsMap) {
+ List validDataSourceProcessors = validDataSourceProcessorsMap.entrySet().stream()
+ .sorted(Map.Entry.comparingByValue().reversed())
+ .map(Map.Entry::getKey)
+ .collect(Collectors.toList());
+
+ return validDataSourceProcessors;
+ }
}
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/CaseStatusIconCellRenderer.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java
old mode 100755
new mode 100644
similarity index 61%
rename from Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CaseStatusIconCellRenderer.java
rename to Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java
index 0010cc90ee..a4066e6c15
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/CaseStatusIconCellRenderer.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java
@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
- * Copyright 2015 Basis Technology Corp.
+ * Copyright 2017 Basis Technology Corp.
* Contact: carrier sleuthkit org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -23,27 +23,34 @@ import javax.swing.ImageIcon;
import javax.swing.JTable;
import static javax.swing.SwingConstants.CENTER;
import org.openide.util.ImageUtilities;
+import org.openide.util.NbBundle.Messages;
+import org.sleuthkit.autopsy.guiutils.GrayableCellRenderer;
+import org.sleuthkit.autopsy.guiutils.StatusIconCellRenderer;
/**
- * A JTable cell renderer that represents an auto ingest alert file exists flag
- * as a center-aligned icon, and grays out the cell if the table is disabled.
+ * A JTable cell renderer that represents whether the priority value of a job
+ * has ever been increased, tick if prioritized nothing if not.
*/
-class CaseStatusIconCellRenderer extends GrayableCellRenderer {
+class PrioritizedIconCellRenderer extends GrayableCellRenderer {
+
+ @Messages({
+ "PrioritizedIconCellRenderer.prioritized.tooltiptext=This job has been prioritized. The most recently prioritized job should be processed next.",
+ "PrioritizedIconCellRenderer.notPrioritized.tooltiptext=This job has not been prioritized."
+ })
private static final long serialVersionUID = 1L;
static final ImageIcon checkedIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/experimental/images/tick.png", false));
- static final ImageIcon warningIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/experimental/images/warning16.png", false));
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
setHorizontalAlignment(CENTER);
- if ((value instanceof Boolean)) {
- if (true == (Boolean) value) {
- setIcon(warningIcon);
- setToolTipText(org.openide.util.NbBundle.getMessage(CaseStatusIconCellRenderer.class, "CaseStatusIconCellRenderer.tooltiptext.warning"));
+ if ((value instanceof Integer)) {
+ if ((int) value == 0) {
+ setIcon(null);
+ setToolTipText(org.openide.util.NbBundle.getMessage(PrioritizedIconCellRenderer.class, "PrioritizedIconCellRenderer.notPrioritized.tooltiptext"));
} else {
setIcon(checkedIcon);
- setToolTipText(org.openide.util.NbBundle.getMessage(CaseStatusIconCellRenderer.class, "CaseStatusIconCellRenderer.tooltiptext.ok"));
+ setToolTipText(org.openide.util.NbBundle.getMessage(PrioritizedIconCellRenderer.class, "PrioritizedIconCellRenderer.prioritized.tooltiptext"));
}
}
grayCellIfTableNotEnabled(table, isSelected);
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/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 20c8c7a981..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 @@
-
-
-
-
@@ -56,18 +52,71 @@
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -79,542 +128,65 @@
-
-
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -649,6 +221,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..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;
@@ -56,7 +57,7 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
enum OptionsUiMode {
- STANDALONE, AIM, REVIEW, DOWNLOADING_CONFIGURATION
+ STANDALONE, AIM, DOWNLOADING_CONFIGURATION
};
/**
@@ -127,21 +128,10 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
if (inStartup) {
UserPreferences.SelectedMode storedMode = UserPreferences.getMode();
inputPathTextField.requestFocusInWindow();
- if (null != storedMode) {
- switch (storedMode) {
- case REVIEW:
- jRadioButtonReview.setSelected(true);
- enableOptionsBasedOnMode(OptionsUiMode.REVIEW);
- break;
- case AUTOINGEST:
- jRadioButtonAutomated.setSelected(true);
- enableOptionsBasedOnMode(OptionsUiMode.AIM);
- break;
- default:
- cbJoinAutoIngestCluster.setSelected(false);
- enableOptionsBasedOnMode(OptionsUiMode.STANDALONE);
- break;
- }
+ if (storedMode == UserPreferences.SelectedMode.AUTOINGEST) {
+ enableOptionsBasedOnMode(OptionsUiMode.AIM);
+ } else if (storedMode != null) {
+ enableOptionsBasedOnMode(OptionsUiMode.STANDALONE);
}
}
@@ -207,22 +197,12 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
* Save mode to persistent storage.
*/
void store() {
- boolean needsRestart = false;
- UserPreferences.SelectedMode storedMode = UserPreferences.getMode();
-
+ boolean needsRestart = (cbJoinAutoIngestCluster.isSelected() != AutoIngestUserPreferences.getJoinAutoModeCluster());
+
AutoIngestUserPreferences.setJoinAutoModeCluster(cbJoinAutoIngestCluster.isSelected());
if (!cbJoinAutoIngestCluster.isSelected()) {
- if(storedMode == UserPreferences.SelectedMode.AUTOINGEST) {
- needsRestart = true;
- }
-
UserPreferences.setMode(UserPreferences.SelectedMode.STANDALONE);
- }
- else if (jRadioButtonAutomated.isSelected()) {
- if (storedMode == UserPreferences.SelectedMode.REVIEW) {
- needsRestart = true;
- }
-
+ } else {
UserPreferences.setMode(UserPreferences.SelectedMode.AUTOINGEST);
String imageFolderPath = getNormalizedFolderPath(inputPathTextField.getText().trim());
AutoIngestUserPreferences.setAutoModeImageFolder(imageFolderPath);
@@ -234,15 +214,8 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
AutoIngestUserPreferences.setSharedConfigFolder(globalSettingsPath);
AutoIngestUserPreferences.setSharedConfigMaster(masterNodeCheckBox.isSelected());
}
- } else if (jRadioButtonReview.isSelected()) {
- if (storedMode == UserPreferences.SelectedMode.AUTOINGEST) {
- needsRestart = true;
- }
-
- UserPreferences.setMode(UserPreferences.SelectedMode.REVIEW);
- String resultsFolderPath = getNormalizedFolderPath(outputPathTextField.getText().trim());
- AutoIngestUserPreferences.setAutoModeResultsFolder(resultsFolderPath);
}
+
if (needsRestart) {
SwingUtilities.invokeLater(() -> {
JOptionPane.showMessageDialog(null,
@@ -306,23 +279,14 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
configButtonErrorTextField.setText("Shared configuration folder is invalid");
}
break;
- case REVIEW:
- jLabelInvalidImageFolder.setVisible(false);
- if (!validateResultsPath()) {
- isValidNodePanel = false;
- }
- break;
-
case STANDALONE:
break;
default:
break;
}
- if (jRadioButtonAutomated.isSelected()) {
- if (sharedConfigCheckbox.isEnabled() && sharedConfigCheckbox.isSelected() && !validSharedConfigSettings()) {
- isValidNodePanel = false;
- }
+ if (sharedConfigCheckbox.isEnabled() && sharedConfigCheckbox.isSelected() && !validSharedConfigSettings()) {
+ isValidNodePanel = false;
}
return isValidNodePanel;
}
@@ -550,7 +514,8 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
}
private void displayIngestJobSettingsPanel() {
-
+ this.getParent().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+
IngestJobSettings ingestJobSettings = new IngestJobSettings(AutoIngestUserPreferences.getAutoModeIngestModuleContextString());
showWarnings(ingestJobSettings);
IngestJobSettingsPanel ingestJobSettingsPanel = new IngestJobSettingsPanel(ingestJobSettings);
@@ -563,6 +528,8 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
ingestJobSettings.save();
showWarnings(ingestJobSettings);
}
+
+ this.getParent().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
private static void showWarnings(IngestJobSettings ingestJobSettings) {
@@ -579,24 +546,17 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
private void enableOptionsBasedOnMode(OptionsUiMode mode) {
if (mode != OptionsUiMode.DOWNLOADING_CONFIGURATION) {
boolean nonMasterSharedConfig = !masterNodeCheckBox.isSelected() && sharedConfigCheckbox.isSelected();
- jRadioButtonAutomated.setEnabled(cbJoinAutoIngestCluster.isSelected());
- jRadioButtonReview.setEnabled(cbJoinAutoIngestCluster.isSelected());
-
jLabelSelectInputFolder.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
inputPathTextField.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
browseInputFolderButton.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
- jLabelSelectOutputFolder.setEnabled((mode == OptionsUiMode.AIM && !nonMasterSharedConfig) || mode == OptionsUiMode.REVIEW);
- outputPathTextField.setEnabled((mode == OptionsUiMode.AIM && !nonMasterSharedConfig) || mode == OptionsUiMode.REVIEW);
- browseOutputFolderButton.setEnabled((mode == OptionsUiMode.AIM && !nonMasterSharedConfig) || mode == OptionsUiMode.REVIEW);
+ jLabelSelectOutputFolder.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
+ outputPathTextField.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
+ browseOutputFolderButton.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
- jPanelSharedConfig.setEnabled(mode == OptionsUiMode.AIM);
-
- jPanelIngestSettings.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
bnEditIngestSettings.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
bnAdvancedSettings.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
bnLogging.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
- jPanelSharedConfig.setEnabled(mode == OptionsUiMode.AIM);
sharedConfigCheckbox.setEnabled(mode == OptionsUiMode.AIM);
masterNodeCheckBox.setEnabled(mode == OptionsUiMode.AIM && sharedConfigCheckbox.isSelected());
bnFileExport.setEnabled(mode == OptionsUiMode.AIM);
@@ -613,14 +573,8 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
private OptionsUiMode getModeFromRadioButtons() {
if (!cbJoinAutoIngestCluster.isSelected()) {
return OptionsUiMode.STANDALONE;
- }
-
- if (jRadioButtonAutomated.isSelected()) {
- return OptionsUiMode.AIM;
- } else if (jRadioButtonReview.isSelected()) {
- return OptionsUiMode.REVIEW;
} else {
- return OptionsUiMode.STANDALONE;
+ return OptionsUiMode.AIM;
}
}
@@ -633,292 +587,51 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
// //GEN-BEGIN:initComponents
private void initComponents() {
- modeRadioButtons = new javax.swing.ButtonGroup();
nodeScrollPane = new javax.swing.JScrollPane();
nodePanel = new javax.swing.JPanel();
- jPanelNodeType = new javax.swing.JPanel();
- jLabelSelectMode = new javax.swing.JLabel();
- jRadioButtonAutomated = new javax.swing.JRadioButton();
- jRadioButtonReview = new javax.swing.JRadioButton();
- jLabelSelectInputFolder = new javax.swing.JLabel();
- inputPathTextField = new javax.swing.JTextField();
- browseInputFolderButton = new javax.swing.JButton();
- jLabelSelectOutputFolder = new javax.swing.JLabel();
- outputPathTextField = new javax.swing.JTextField();
- browseOutputFolderButton = new javax.swing.JButton();
- jLabelInvalidImageFolder = new javax.swing.JLabel();
- jLabelInvalidResultsFolder = new javax.swing.JLabel();
- jLabel1 = new javax.swing.JLabel();
- jPanelSharedConfig = new javax.swing.JPanel();
- sharedConfigCheckbox = new javax.swing.JCheckBox();
- sharedSettingsTextField = new javax.swing.JTextField();
- browseSharedSettingsButton = new javax.swing.JButton();
- sharedSettingsErrorTextField = new javax.swing.JTextField();
- masterNodeCheckBox = new javax.swing.JCheckBox();
- uploadButton = new javax.swing.JButton();
- downloadButton = new javax.swing.JButton();
- jLabelCurrentTask = new javax.swing.JLabel();
- pbTaskInProgress = new javax.swing.JProgressBar();
- jLabelTaskDescription = new javax.swing.JLabel();
- configButtonErrorTextField = new javax.swing.JTextField();
- jSeparator1 = new javax.swing.JSeparator();
- jPanelIngestSettings = new javax.swing.JPanel();
+ cbJoinAutoIngestCluster = new javax.swing.JCheckBox();
+ tbOops = new javax.swing.JTextField();
bnEditIngestSettings = new javax.swing.JButton();
bnAdvancedSettings = new javax.swing.JButton();
bnFileExport = new javax.swing.JButton();
bnLogging = new javax.swing.JButton();
- cbJoinAutoIngestCluster = new javax.swing.JCheckBox();
- tbOops = new javax.swing.JTextField();
+ browseOutputFolderButton = new javax.swing.JButton();
+ browseInputFolderButton = new javax.swing.JButton();
+ inputPathTextField = new javax.swing.JTextField();
+ outputPathTextField = new javax.swing.JTextField();
+ jLabelInvalidResultsFolder = new javax.swing.JLabel();
+ jLabelInvalidImageFolder = new javax.swing.JLabel();
+ jLabelSelectInputFolder = new javax.swing.JLabel();
+ jLabelSelectOutputFolder = new javax.swing.JLabel();
+ sharedConfigCheckbox = new javax.swing.JCheckBox();
+ sharedSettingsErrorTextField = new javax.swing.JTextField();
+ sharedSettingsTextField = new javax.swing.JTextField();
+ browseSharedSettingsButton = new javax.swing.JButton();
+ downloadButton = new javax.swing.JButton();
+ configButtonErrorTextField = new javax.swing.JTextField();
+ pbTaskInProgress = new javax.swing.JProgressBar();
+ jLabelTaskDescription = new javax.swing.JLabel();
+ jLabelCurrentTask = new javax.swing.JLabel();
+ uploadButton = new javax.swing.JButton();
+ masterNodeCheckBox = new javax.swing.JCheckBox();
nodeScrollPane.setMinimumSize(new java.awt.Dimension(0, 0));
nodePanel.setMinimumSize(new java.awt.Dimension(100, 100));
- jPanelNodeType.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jPanelNodeType.border.title"))); // NOI18N
- jPanelNodeType.setMinimumSize(new java.awt.Dimension(50, 50));
-
- org.openide.awt.Mnemonics.setLocalizedText(jLabelSelectMode, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelSelectMode.text")); // NOI18N
-
- modeRadioButtons.add(jRadioButtonAutomated);
- jRadioButtonAutomated.setSelected(true);
- org.openide.awt.Mnemonics.setLocalizedText(jRadioButtonAutomated, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jRadioButtonAutomated.text")); // NOI18N
- jRadioButtonAutomated.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jRadioButtonAutomated.toolTipText")); // NOI18N
- jRadioButtonAutomated.addActionListener(new java.awt.event.ActionListener() {
+ cbJoinAutoIngestCluster.setFont(cbJoinAutoIngestCluster.getFont().deriveFont(cbJoinAutoIngestCluster.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
+ org.openide.awt.Mnemonics.setLocalizedText(cbJoinAutoIngestCluster, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.cbJoinAutoIngestCluster.text")); // NOI18N
+ cbJoinAutoIngestCluster.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
- jRadioButtonAutomatedActionPerformed(evt);
+ cbJoinAutoIngestClusterActionPerformed(evt);
}
});
- modeRadioButtons.add(jRadioButtonReview);
- org.openide.awt.Mnemonics.setLocalizedText(jRadioButtonReview, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jRadioButtonReview.text")); // NOI18N
- jRadioButtonReview.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jRadioButtonReview.toolTipText")); // NOI18N
- jRadioButtonReview.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- jRadioButtonReviewActionPerformed(evt);
- }
- });
-
- org.openide.awt.Mnemonics.setLocalizedText(jLabelSelectInputFolder, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelSelectInputFolder.text")); // NOI18N
- jLabelSelectInputFolder.setVerticalAlignment(javax.swing.SwingConstants.BOTTOM);
-
- inputPathTextField.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.inputPathTextField.text")); // NOI18N
- inputPathTextField.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.inputPathTextField.toolTipText")); // NOI18N
-
- org.openide.awt.Mnemonics.setLocalizedText(browseInputFolderButton, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.browseInputFolderButton.text")); // NOI18N
- browseInputFolderButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- browseInputFolderButtonActionPerformed(evt);
- }
- });
-
- org.openide.awt.Mnemonics.setLocalizedText(jLabelSelectOutputFolder, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelSelectOutputFolder.text")); // NOI18N
- jLabelSelectOutputFolder.setVerticalAlignment(javax.swing.SwingConstants.BOTTOM);
-
- outputPathTextField.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.outputPathTextField.text")); // NOI18N
- outputPathTextField.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.outputPathTextField.toolTipText")); // NOI18N
-
- org.openide.awt.Mnemonics.setLocalizedText(browseOutputFolderButton, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.browseOutputFolderButton.text")); // NOI18N
- browseOutputFolderButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- browseOutputFolderButtonActionPerformed(evt);
- }
- });
-
- jLabelInvalidImageFolder.setForeground(new java.awt.Color(255, 0, 0));
- org.openide.awt.Mnemonics.setLocalizedText(jLabelInvalidImageFolder, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelInvalidImageFolder.text")); // NOI18N
-
- jLabelInvalidResultsFolder.setForeground(new java.awt.Color(255, 0, 0));
- org.openide.awt.Mnemonics.setLocalizedText(jLabelInvalidResultsFolder, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelInvalidResultsFolder.text")); // NOI18N
-
- jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/experimental/images/AIM.png"))); // NOI18N
- org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabel1.text")); // NOI18N
-
- javax.swing.GroupLayout jPanelNodeTypeLayout = new javax.swing.GroupLayout(jPanelNodeType);
- jPanelNodeType.setLayout(jPanelNodeTypeLayout);
- jPanelNodeTypeLayout.setHorizontalGroup(
- jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(jPanelNodeTypeLayout.createSequentialGroup()
- .addContainerGap()
- .addGroup(jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(jPanelNodeTypeLayout.createSequentialGroup()
- .addGroup(jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
- .addComponent(outputPathTextField, javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(inputPathTextField, javax.swing.GroupLayout.Alignment.LEADING))
- .addGap(10, 10, 10)
- .addGroup(jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(browseInputFolderButton, javax.swing.GroupLayout.Alignment.TRAILING)
- .addComponent(browseOutputFolderButton, javax.swing.GroupLayout.Alignment.TRAILING)))
- .addGroup(jPanelNodeTypeLayout.createSequentialGroup()
- .addGroup(jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(jLabelSelectMode)
- .addComponent(jRadioButtonReview)
- .addComponent(jRadioButtonAutomated))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- .addComponent(jLabel1))
- .addGroup(jPanelNodeTypeLayout.createSequentialGroup()
- .addComponent(jLabelSelectInputFolder)
- .addGap(18, 18, 18)
- .addComponent(jLabelInvalidImageFolder, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
- .addGroup(jPanelNodeTypeLayout.createSequentialGroup()
- .addComponent(jLabelSelectOutputFolder)
- .addGap(18, 18, 18)
- .addComponent(jLabelInvalidResultsFolder, javax.swing.GroupLayout.PREFERRED_SIZE, 544, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addGap(0, 0, Short.MAX_VALUE)))
- .addContainerGap())
- );
- jPanelNodeTypeLayout.setVerticalGroup(
- jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(jPanelNodeTypeLayout.createSequentialGroup()
- .addGroup(jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(jPanelNodeTypeLayout.createSequentialGroup()
- .addContainerGap()
- .addComponent(jLabelSelectMode)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addComponent(jRadioButtonAutomated)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(jRadioButtonReview))
- .addComponent(jLabel1))
- .addGap(1, 1, 1)
- .addGroup(jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(jLabelSelectInputFolder)
- .addComponent(jLabelInvalidImageFolder))
- .addGap(1, 1, 1)
- .addGroup(jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(inputPathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addComponent(browseInputFolderButton))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addGroup(jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(jLabelSelectOutputFolder, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addComponent(jLabelInvalidResultsFolder))
- .addGap(1, 1, 1)
- .addGroup(jPanelNodeTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(browseOutputFolderButton)
- .addComponent(outputPathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addGap(0, 0, Short.MAX_VALUE))
- );
-
- jPanelSharedConfig.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jPanelSharedConfig.border.title"))); // NOI18N
-
- org.openide.awt.Mnemonics.setLocalizedText(sharedConfigCheckbox, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.sharedConfigCheckbox.text")); // NOI18N
- sharedConfigCheckbox.setMaximumSize(new java.awt.Dimension(191, 14));
- sharedConfigCheckbox.setMinimumSize(new java.awt.Dimension(191, 14));
- sharedConfigCheckbox.setPreferredSize(new java.awt.Dimension(191, 14));
- sharedConfigCheckbox.addItemListener(new java.awt.event.ItemListener() {
- public void itemStateChanged(java.awt.event.ItemEvent evt) {
- sharedConfigCheckboxItemStateChanged(evt);
- }
- });
-
- sharedSettingsTextField.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.sharedSettingsTextField.text")); // NOI18N
- sharedSettingsTextField.setEnabled(false);
-
- org.openide.awt.Mnemonics.setLocalizedText(browseSharedSettingsButton, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.browseSharedSettingsButton.text")); // NOI18N
- browseSharedSettingsButton.setEnabled(false);
- browseSharedSettingsButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- browseSharedSettingsButtonActionPerformed(evt);
- }
- });
-
- sharedSettingsErrorTextField.setEditable(false);
- sharedSettingsErrorTextField.setForeground(new java.awt.Color(255, 0, 0));
- sharedSettingsErrorTextField.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.sharedSettingsErrorTextField.text")); // NOI18N
- sharedSettingsErrorTextField.setBorder(null);
-
- org.openide.awt.Mnemonics.setLocalizedText(masterNodeCheckBox, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.masterNodeCheckBox.text")); // NOI18N
- masterNodeCheckBox.setEnabled(false);
- masterNodeCheckBox.addItemListener(new java.awt.event.ItemListener() {
- public void itemStateChanged(java.awt.event.ItemEvent evt) {
- masterNodeCheckBoxItemStateChanged(evt);
- }
- });
-
- org.openide.awt.Mnemonics.setLocalizedText(uploadButton, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.uploadButton.text")); // NOI18N
- uploadButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- uploadButtonActionPerformed(evt);
- }
- });
-
- org.openide.awt.Mnemonics.setLocalizedText(downloadButton, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.downloadButton.text")); // NOI18N
- downloadButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- downloadButtonActionPerformed(evt);
- }
- });
-
- org.openide.awt.Mnemonics.setLocalizedText(jLabelCurrentTask, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelCurrentTask.text")); // NOI18N
-
- org.openide.awt.Mnemonics.setLocalizedText(jLabelTaskDescription, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelTaskDescription.text")); // NOI18N
-
- configButtonErrorTextField.setEditable(false);
- configButtonErrorTextField.setForeground(new java.awt.Color(255, 0, 0));
- configButtonErrorTextField.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.configButtonErrorTextField.text")); // NOI18N
- configButtonErrorTextField.setBorder(null);
-
- javax.swing.GroupLayout jPanelSharedConfigLayout = new javax.swing.GroupLayout(jPanelSharedConfig);
- jPanelSharedConfig.setLayout(jPanelSharedConfigLayout);
- jPanelSharedConfigLayout.setHorizontalGroup(
- jPanelSharedConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(jPanelSharedConfigLayout.createSequentialGroup()
- .addGap(10, 10, 10)
- .addComponent(jLabelCurrentTask)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addComponent(jLabelTaskDescription, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- .addContainerGap())
- .addGroup(jPanelSharedConfigLayout.createSequentialGroup()
- .addContainerGap()
- .addGroup(jPanelSharedConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(jPanelSharedConfigLayout.createSequentialGroup()
- .addComponent(sharedSettingsTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 400, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(browseSharedSettingsButton, javax.swing.GroupLayout.PREFERRED_SIZE, 143, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addComponent(uploadButton, javax.swing.GroupLayout.PREFERRED_SIZE, 143, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addGroup(jPanelSharedConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
- .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanelSharedConfigLayout.createSequentialGroup()
- .addComponent(downloadButton, javax.swing.GroupLayout.PREFERRED_SIZE, 143, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addComponent(configButtonErrorTextField))
- .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanelSharedConfigLayout.createSequentialGroup()
- .addComponent(sharedConfigCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addComponent(sharedSettingsErrorTextField))
- .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 692, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addComponent(pbTaskInProgress, javax.swing.GroupLayout.PREFERRED_SIZE, 695, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addComponent(masterNodeCheckBox))
- .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
- );
- jPanelSharedConfigLayout.setVerticalGroup(
- jPanelSharedConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(jPanelSharedConfigLayout.createSequentialGroup()
- .addContainerGap()
- .addGroup(jPanelSharedConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(sharedConfigCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addComponent(sharedSettingsErrorTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addGroup(jPanelSharedConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(sharedSettingsTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addComponent(browseSharedSettingsButton))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addGroup(jPanelSharedConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(downloadButton)
- .addComponent(configButtonErrorTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addGap(1, 1, 1)
- .addComponent(masterNodeCheckBox, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(uploadButton)
- .addGap(8, 8, 8)
- .addGroup(jPanelSharedConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(jLabelCurrentTask)
- .addComponent(jLabelTaskDescription))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(pbTaskInProgress, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
- );
-
- jPanelIngestSettings.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jPanelIngestSettings.border.title"))); // NOI18N
+ tbOops.setEditable(false);
+ tbOops.setFont(tbOops.getFont().deriveFont(tbOops.getFont().getStyle() | java.awt.Font.BOLD, 12));
+ tbOops.setForeground(new java.awt.Color(255, 0, 0));
+ tbOops.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.tbOops.text")); // NOI18N
+ tbOops.setBorder(null);
org.openide.awt.Mnemonics.setLocalizedText(bnEditIngestSettings, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.bnEditIngestSettings.text")); // NOI18N
bnEditIngestSettings.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.bnEditIngestSettings.toolTipText")); // NOI18N
@@ -949,46 +662,94 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
}
});
- javax.swing.GroupLayout jPanelIngestSettingsLayout = new javax.swing.GroupLayout(jPanelIngestSettings);
- jPanelIngestSettings.setLayout(jPanelIngestSettingsLayout);
- jPanelIngestSettingsLayout.setHorizontalGroup(
- jPanelIngestSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(jPanelIngestSettingsLayout.createSequentialGroup()
- .addContainerGap()
- .addComponent(bnEditIngestSettings, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(bnAdvancedSettings, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(bnFileExport, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(bnLogging, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
- );
- jPanelIngestSettingsLayout.setVerticalGroup(
- jPanelIngestSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(jPanelIngestSettingsLayout.createSequentialGroup()
- .addContainerGap()
- .addGroup(jPanelIngestSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(bnEditIngestSettings)
- .addComponent(bnFileExport)
- .addComponent(bnAdvancedSettings)
- .addComponent(bnLogging))
- .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
- );
-
- cbJoinAutoIngestCluster.setFont(cbJoinAutoIngestCluster.getFont().deriveFont(cbJoinAutoIngestCluster.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
- org.openide.awt.Mnemonics.setLocalizedText(cbJoinAutoIngestCluster, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.cbJoinAutoIngestCluster.text")); // NOI18N
- cbJoinAutoIngestCluster.addActionListener(new java.awt.event.ActionListener() {
+ org.openide.awt.Mnemonics.setLocalizedText(browseOutputFolderButton, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.browseOutputFolderButton.text")); // NOI18N
+ browseOutputFolderButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
- cbJoinAutoIngestClusterActionPerformed(evt);
+ browseOutputFolderButtonActionPerformed(evt);
}
});
- tbOops.setEditable(false);
- tbOops.setFont(tbOops.getFont().deriveFont(tbOops.getFont().getStyle() | java.awt.Font.BOLD, 12));
- tbOops.setForeground(new java.awt.Color(255, 0, 0));
- tbOops.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.tbOops.text")); // NOI18N
- tbOops.setBorder(null);
+ org.openide.awt.Mnemonics.setLocalizedText(browseInputFolderButton, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.browseInputFolderButton.text")); // NOI18N
+ browseInputFolderButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ browseInputFolderButtonActionPerformed(evt);
+ }
+ });
+
+ inputPathTextField.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.inputPathTextField.text")); // NOI18N
+ inputPathTextField.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.inputPathTextField.toolTipText")); // NOI18N
+
+ outputPathTextField.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.outputPathTextField.text")); // NOI18N
+ outputPathTextField.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.outputPathTextField.toolTipText")); // NOI18N
+
+ jLabelInvalidResultsFolder.setForeground(new java.awt.Color(255, 0, 0));
+ org.openide.awt.Mnemonics.setLocalizedText(jLabelInvalidResultsFolder, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelInvalidResultsFolder.text")); // NOI18N
+
+ jLabelInvalidImageFolder.setForeground(new java.awt.Color(255, 0, 0));
+ org.openide.awt.Mnemonics.setLocalizedText(jLabelInvalidImageFolder, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelInvalidImageFolder.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(jLabelSelectInputFolder, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelSelectInputFolder.text")); // NOI18N
+ jLabelSelectInputFolder.setVerticalAlignment(javax.swing.SwingConstants.BOTTOM);
+
+ org.openide.awt.Mnemonics.setLocalizedText(jLabelSelectOutputFolder, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelSelectOutputFolder.text")); // NOI18N
+ jLabelSelectOutputFolder.setVerticalAlignment(javax.swing.SwingConstants.BOTTOM);
+
+ org.openide.awt.Mnemonics.setLocalizedText(sharedConfigCheckbox, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.sharedConfigCheckbox.text")); // NOI18N
+ sharedConfigCheckbox.setMaximumSize(new java.awt.Dimension(191, 14));
+ sharedConfigCheckbox.setMinimumSize(new java.awt.Dimension(191, 14));
+ sharedConfigCheckbox.setPreferredSize(new java.awt.Dimension(191, 14));
+ sharedConfigCheckbox.addItemListener(new java.awt.event.ItemListener() {
+ public void itemStateChanged(java.awt.event.ItemEvent evt) {
+ sharedConfigCheckboxItemStateChanged(evt);
+ }
+ });
+
+ sharedSettingsErrorTextField.setEditable(false);
+ sharedSettingsErrorTextField.setForeground(new java.awt.Color(255, 0, 0));
+ sharedSettingsErrorTextField.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.sharedSettingsErrorTextField.text")); // NOI18N
+ sharedSettingsErrorTextField.setBorder(null);
+
+ sharedSettingsTextField.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.sharedSettingsTextField.text")); // NOI18N
+ sharedSettingsTextField.setEnabled(false);
+
+ org.openide.awt.Mnemonics.setLocalizedText(browseSharedSettingsButton, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.browseSharedSettingsButton.text")); // NOI18N
+ browseSharedSettingsButton.setEnabled(false);
+ browseSharedSettingsButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ browseSharedSettingsButtonActionPerformed(evt);
+ }
+ });
+
+ org.openide.awt.Mnemonics.setLocalizedText(downloadButton, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.downloadButton.text")); // NOI18N
+ downloadButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ downloadButtonActionPerformed(evt);
+ }
+ });
+
+ configButtonErrorTextField.setEditable(false);
+ configButtonErrorTextField.setForeground(new java.awt.Color(255, 0, 0));
+ configButtonErrorTextField.setText(org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.configButtonErrorTextField.text")); // NOI18N
+ configButtonErrorTextField.setBorder(null);
+
+ org.openide.awt.Mnemonics.setLocalizedText(jLabelTaskDescription, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelTaskDescription.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(jLabelCurrentTask, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.jLabelCurrentTask.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(uploadButton, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.uploadButton.text")); // NOI18N
+ uploadButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ uploadButtonActionPerformed(evt);
+ }
+ });
+
+ org.openide.awt.Mnemonics.setLocalizedText(masterNodeCheckBox, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.masterNodeCheckBox.text")); // NOI18N
+ masterNodeCheckBox.setEnabled(false);
+ masterNodeCheckBox.addItemListener(new java.awt.event.ItemListener() {
+ public void itemStateChanged(java.awt.event.ItemEvent evt) {
+ masterNodeCheckBoxItemStateChanged(evt);
+ }
+ });
javax.swing.GroupLayout nodePanelLayout = new javax.swing.GroupLayout(nodePanel);
nodePanel.setLayout(nodePanelLayout);
@@ -998,14 +759,56 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
.addContainerGap()
.addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(nodePanelLayout.createSequentialGroup()
- .addComponent(cbJoinAutoIngestCluster, javax.swing.GroupLayout.PREFERRED_SIZE, 171, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(jLabelCurrentTask)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(jLabelTaskDescription, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addGroup(nodePanelLayout.createSequentialGroup()
+ .addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(outputPathTextField, javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(inputPathTextField, javax.swing.GroupLayout.Alignment.LEADING))
+ .addGap(10, 10, 10)
+ .addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(browseInputFolderButton, javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(browseOutputFolderButton, javax.swing.GroupLayout.Alignment.TRAILING)))
+ .addGroup(nodePanelLayout.createSequentialGroup()
+ .addComponent(jLabelSelectInputFolder)
.addGap(18, 18, 18)
- .addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, 465, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
- .addComponent(jPanelNodeType, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- .addComponent(jPanelSharedConfig, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- .addComponent(jPanelIngestSettings, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
- .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addComponent(jLabelInvalidImageFolder, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addGroup(nodePanelLayout.createSequentialGroup()
+ .addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(uploadButton, javax.swing.GroupLayout.PREFERRED_SIZE, 143, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(pbTaskInProgress, javax.swing.GroupLayout.PREFERRED_SIZE, 695, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(masterNodeCheckBox)
+ .addGroup(nodePanelLayout.createSequentialGroup()
+ .addComponent(cbJoinAutoIngestCluster, javax.swing.GroupLayout.PREFERRED_SIZE, 171, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(18, 18, 18)
+ .addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, 465, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(nodePanelLayout.createSequentialGroup()
+ .addComponent(bnEditIngestSettings, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(bnAdvancedSettings, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(bnFileExport, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(bnLogging, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(nodePanelLayout.createSequentialGroup()
+ .addComponent(jLabelSelectOutputFolder)
+ .addGap(18, 18, 18)
+ .addComponent(jLabelInvalidResultsFolder, javax.swing.GroupLayout.PREFERRED_SIZE, 544, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(nodePanelLayout.createSequentialGroup()
+ .addComponent(sharedConfigCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(sharedSettingsErrorTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(nodePanelLayout.createSequentialGroup()
+ .addComponent(sharedSettingsTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 400, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(browseSharedSettingsButton, javax.swing.GroupLayout.PREFERRED_SIZE, 143, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(nodePanelLayout.createSequentialGroup()
+ .addComponent(downloadButton, javax.swing.GroupLayout.PREFERRED_SIZE, 143, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(configButtonErrorTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 396, javax.swing.GroupLayout.PREFERRED_SIZE)))
+ .addGap(0, 32, Short.MAX_VALUE)))
+ .addContainerGap())
);
nodePanelLayout.setVerticalGroup(
nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@@ -1014,12 +817,51 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
.addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(cbJoinAutoIngestCluster)
.addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addGap(3, 3, 3)
- .addComponent(jPanelNodeType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(18, 18, 18)
+ .addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabelSelectInputFolder)
+ .addComponent(jLabelInvalidImageFolder))
+ .addGap(1, 1, 1)
+ .addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(inputPathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(browseInputFolderButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(jPanelIngestSettings, javax.swing.GroupLayout.PREFERRED_SIZE, 62, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabelSelectOutputFolder, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(jLabelInvalidResultsFolder))
+ .addGap(1, 1, 1)
+ .addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(browseOutputFolderButton)
+ .addComponent(outputPathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGap(25, 25, 25)
+ .addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(bnEditIngestSettings)
+ .addComponent(bnFileExport)
+ .addComponent(bnAdvancedSettings)
+ .addComponent(bnLogging))
+ .addGap(18, 18, 18)
+ .addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(sharedConfigCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(sharedSettingsErrorTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(jPanelSharedConfig, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(sharedSettingsTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(browseSharedSettingsButton))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(downloadButton)
+ .addComponent(configButtonErrorTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGap(18, 18, 18)
+ .addComponent(masterNodeCheckBox, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(uploadButton)
+ .addGap(8, 8, 8)
+ .addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabelCurrentTask)
+ .addComponent(jLabelTaskDescription))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(pbTaskInProgress, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap(161, Short.MAX_VALUE))
);
nodeScrollPane.setViewportView(nodePanel);
@@ -1039,31 +881,35 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
);
}// //GEN-END:initComponents
- private void browseSharedSettingsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseSharedSettingsButtonActionPerformed
-
- String oldText = sharedSettingsTextField.getText().trim();
- // set the current directory of the FileChooser if the oldText is valid
- File currentDir = new File(oldText);
- if (currentDir.exists()) {
- fc.setCurrentDirectory(currentDir);
- }
-
- fc.setDialogTitle("Select shared configuration folder:");
- fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
-
- int retval = fc.showOpenDialog(this);
- if (retval == JFileChooser.APPROVE_OPTION) {
- String path = fc.getSelectedFile().getPath();
- sharedSettingsTextField.setText(path);
- validateSettings();
- controller.changed();
- }
- }//GEN-LAST:event_browseSharedSettingsButtonActionPerformed
-
boolean permissionsAppropriate(String path) {
return FileUtil.hasReadWriteAccess(Paths.get(path));
}
+ private void setSharedConfigEnable() {
+ setEnabledStateForSharedConfiguration();
+ if (sharedConfigCheckbox.isEnabled() && sharedConfigCheckbox.isSelected()) {
+ sharedSettingsTextField.setEnabled(true);
+ browseSharedSettingsButton.setEnabled(true);
+ masterNodeCheckBox.setEnabled(true);
+ downloadButton.setEnabled(true);
+ validateSettings();
+ controller.changed();
+ } else {
+ sharedSettingsTextField.setEnabled(false);
+ browseSharedSettingsButton.setEnabled(false);
+ masterNodeCheckBox.setEnabled(false);
+ downloadButton.setEnabled(false);
+ sharedSettingsErrorTextField.setText("");
+ validateSettings();
+ controller.changed();
+ }
+ }
+
+ private void cbJoinAutoIngestClusterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbJoinAutoIngestClusterActionPerformed
+ enableOptionsBasedOnMode(getModeFromRadioButtons());
+ controller.changed();
+ }//GEN-LAST:event_cbJoinAutoIngestClusterActionPerformed
+
private void downloadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_downloadButtonActionPerformed
// First save the shared config folder and solr settings to the properties
String globalSettingsPath = getNormalizedFolderPath(sharedSettingsTextField.getText().trim());
@@ -1100,31 +946,6 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
}
}//GEN-LAST:event_uploadButtonActionPerformed
- private void sharedConfigCheckboxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_sharedConfigCheckboxItemStateChanged
- // Enable the global settings text box and browse button iff the checkbox is checked and enabled
- setSharedConfigEnable();
- }//GEN-LAST:event_sharedConfigCheckboxItemStateChanged
-
- private void setSharedConfigEnable() {
- setEnabledStateForSharedConfiguration();
- if (sharedConfigCheckbox.isEnabled() && sharedConfigCheckbox.isSelected() && jRadioButtonAutomated.isSelected()) {
- sharedSettingsTextField.setEnabled(true);
- browseSharedSettingsButton.setEnabled(true);
- masterNodeCheckBox.setEnabled(true);
- downloadButton.setEnabled(true);
- validateSettings();
- controller.changed();
- } else {
- sharedSettingsTextField.setEnabled(false);
- browseSharedSettingsButton.setEnabled(false);
- masterNodeCheckBox.setEnabled(false);
- downloadButton.setEnabled(false);
- sharedSettingsErrorTextField.setText("");
- validateSettings();
- controller.changed();
- }
- }
-
private void masterNodeCheckBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_masterNodeCheckBoxItemStateChanged
// Enable the global settings text box and browse button iff the checkbox is checked and enabled
setEnabledStateForSharedConfiguration();
@@ -1137,10 +958,31 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
}
}//GEN-LAST:event_masterNodeCheckBoxItemStateChanged
- private void cbJoinAutoIngestClusterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbJoinAutoIngestClusterActionPerformed
- enableOptionsBasedOnMode(getModeFromRadioButtons());
- controller.changed();
- }//GEN-LAST:event_cbJoinAutoIngestClusterActionPerformed
+ private void browseSharedSettingsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseSharedSettingsButtonActionPerformed
+
+ String oldText = sharedSettingsTextField.getText().trim();
+ // set the current directory of the FileChooser if the oldText is valid
+ File currentDir = new File(oldText);
+ if (currentDir.exists()) {
+ fc.setCurrentDirectory(currentDir);
+ }
+
+ fc.setDialogTitle("Select shared configuration folder:");
+ fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+
+ int retval = fc.showOpenDialog(this);
+ if (retval == JFileChooser.APPROVE_OPTION) {
+ String path = fc.getSelectedFile().getPath();
+ sharedSettingsTextField.setText(path);
+ validateSettings();
+ controller.changed();
+ }
+ }//GEN-LAST:event_browseSharedSettingsButtonActionPerformed
+
+ private void sharedConfigCheckboxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_sharedConfigCheckboxItemStateChanged
+ // Enable the global settings text box and browse button iff the checkbox is checked and enabled
+ setSharedConfigEnable();
+ }//GEN-LAST:event_sharedConfigCheckboxItemStateChanged
private void browseOutputFolderButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseOutputFolderButtonActionPerformed
String oldText = outputPathTextField.getText().trim();
@@ -1182,24 +1024,6 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
}
}//GEN-LAST:event_browseInputFolderButtonActionPerformed
- private void jRadioButtonReviewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioButtonReviewActionPerformed
- if (cbJoinAutoIngestCluster.isSelected()) {
- enableOptionsBasedOnMode(OptionsUiMode.REVIEW);
- setSharedConfigEnable();
- validateSettings();
- controller.changed();
- }
- }//GEN-LAST:event_jRadioButtonReviewActionPerformed
-
- private void jRadioButtonAutomatedActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioButtonAutomatedActionPerformed
- if (cbJoinAutoIngestCluster.isSelected()) {
- enableOptionsBasedOnMode(OptionsUiMode.AIM);
- setSharedConfigEnable();
- validateSettings();
- controller.changed();
- }
- }//GEN-LAST:event_jRadioButtonAutomatedActionPerformed
-
private void bnLoggingActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnLoggingActionPerformed
JDialog jDialog = new JDialog();
NodeStatusLogPanel loggingPanel = new NodeStatusLogPanel(jDialog);
@@ -1242,9 +1066,9 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
private void bnAdvancedSettingsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnAdvancedSettingsActionPerformed
AdvancedAutoIngestSettingsPanel advancedAutoIngestSettingsPanel = new AdvancedAutoIngestSettingsPanel(getModeFromRadioButtons());
if (JOptionPane.showConfirmDialog(null, advancedAutoIngestSettingsPanel,
- NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.AdvancedAutoIngestSettingsPanel.Title"),
- JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE) == JOptionPane.OK_OPTION) {
- advancedAutoIngestSettingsPanel.store();
+ NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.AdvancedAutoIngestSettingsPanel.Title"),
+ JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE) == JOptionPane.OK_OPTION) {
+ advancedAutoIngestSettingsPanel.store();
}
}//GEN-LAST:event_bnAdvancedSettingsActionPerformed
@@ -1349,7 +1173,7 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
}
void setEnabledStateForSharedConfiguration() {
- if (jRadioButtonAutomated.isSelected() && cbJoinAutoIngestCluster.isSelected()) {
+ if (cbJoinAutoIngestCluster.isSelected()) {
enableOptionsBasedOnMode(OptionsUiMode.AIM);
}
}
@@ -1361,19 +1185,13 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
bnLogging.setEnabled(enabled);
browseInputFolderButton.setEnabled(enabled);
browseOutputFolderButton.setEnabled(enabled);
- browseSharedSettingsButton.setEnabled(sharedConfigCheckbox.isSelected() && jRadioButtonAutomated.isSelected());
+ browseSharedSettingsButton.setEnabled(sharedConfigCheckbox.isSelected() && cbJoinAutoIngestCluster.isSelected());
configButtonErrorTextField.setEnabled(enabled);
inputPathTextField.setEnabled(enabled);
jLabelInvalidImageFolder.setEnabled(enabled);
jLabelInvalidResultsFolder.setEnabled(enabled);
jLabelSelectInputFolder.setEnabled(enabled);
- jLabelSelectMode.setEnabled(enabled);
jLabelSelectOutputFolder.setEnabled(enabled);
- jPanelIngestSettings.setEnabled(enabled);
- jPanelNodeType.setEnabled(enabled);
- jPanelSharedConfig.setEnabled(enabled);
- jRadioButtonAutomated.setEnabled(enabled);
- jRadioButtonReview.setEnabled(enabled);
outputPathTextField.setEnabled(enabled);
}
@@ -1389,22 +1207,13 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
private javax.swing.JTextField configButtonErrorTextField;
private javax.swing.JButton downloadButton;
private javax.swing.JTextField inputPathTextField;
- private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabelCurrentTask;
private javax.swing.JLabel jLabelInvalidImageFolder;
private javax.swing.JLabel jLabelInvalidResultsFolder;
private javax.swing.JLabel jLabelSelectInputFolder;
- private javax.swing.JLabel jLabelSelectMode;
private javax.swing.JLabel jLabelSelectOutputFolder;
private javax.swing.JLabel jLabelTaskDescription;
- private javax.swing.JPanel jPanelIngestSettings;
- private javax.swing.JPanel jPanelNodeType;
- private javax.swing.JPanel jPanelSharedConfig;
- private javax.swing.JRadioButton jRadioButtonAutomated;
- private javax.swing.JRadioButton jRadioButtonReview;
- private javax.swing.JSeparator jSeparator1;
private javax.swing.JCheckBox masterNodeCheckBox;
- private javax.swing.ButtonGroup modeRadioButtons;
private javax.swing.JPanel nodePanel;
private javax.swing.JScrollPane nodeScrollPane;
private javax.swing.JTextField outputPathTextField;
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
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java
index b715b7d309..1720b4b647 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 (HashDbManager.HashDb hashDb : hashDbManager.getAllHashSets()) {
if (hashDb.hasIndexOnly()) {
results.add(hashDb.getIndexPath());
} else {
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java
index e28cd75654..862635ad4a 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 JPanel
+ * subclass have not been constructed yet, since this panel's
+ * constructor has not been called yet.
+ */
+ if (null != listsManagementPanel) {
+ listsManagementPanel.addPropertyChangeListener(l);
+ }
+ if (null != editListPanel) {
+ editListPanel.addPropertyChangeListener(l);
+ }
}
@Override
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java
index 6836483b30..70d2e69194 100755
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java
@@ -205,7 +205,13 @@ class HighlightedText implements IndexedText {
*/
synchronized private void loadPageInfoFromHits() {
isLiteral = hits.getQuery().isLiteral();
- //organize the hits by page, filter as needed
+
+ /**
+ * Organize the hits by page, filter as needed.
+ * We process *every* keyword here because in the case of a regular
+ * expression search there may be multiple different keyword
+ * hits located in different chunks for the same file/artifact.
+ */
for (Keyword k : hits.getKeywords()) {
for (KeywordHit hit : hits.getResults(k)) {
int chunkID = hit.getChunkId();
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordHit.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordHit.java
index e51c1c2620..f9284e81d9 100755
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordHit.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordHit.java
@@ -38,12 +38,9 @@ class KeywordHit implements Comparable {
private static final String GET_CONTENT_ID_FROM_ARTIFACT_ID = "SELECT obj_id FROM blackboard_artifacts WHERE artifact_id = ";
- private final String solrDocumentId;
private final long solrObjectId;
private final int chunkId;
private final String snippet;
- private final long contentID;
- private final boolean hitOnArtifact;
private final String hit;
/**
@@ -56,14 +53,10 @@ class KeywordHit implements Comparable {
* For some searches (ie substring, regex) this will be
* different than the search term.
*
- * @throws TskCoreException If there is a problem getting the underlying
- * content associated with a hit on the text of an
- * artifact.
*/
- KeywordHit(String solrDocumentId, String snippet, String hit) throws TskCoreException {
+ KeywordHit(String solrDocumentId, String snippet, String hit) {
this.snippet = StringUtils.stripToEmpty(snippet);
this.hit = hit;
- this.solrDocumentId = solrDocumentId;
/*
* Parse the Solr document id to get the Solr object id and chunk id.
@@ -83,28 +76,6 @@ class KeywordHit implements Comparable {
this.solrObjectId = Long.parseLong(split[0]);
this.chunkId = Integer.parseInt(split[1]);
}
-
- //artifacts have negative obj ids
- hitOnArtifact = this.solrObjectId < 0;
-
- if (hitOnArtifact) {
- // If the hit was in an artifact, look up the source content for the artifact.
- SleuthkitCase caseDb = Case.getCurrentCase().getSleuthkitCase();
- try (SleuthkitCase.CaseDbQuery executeQuery =
- caseDb.executeQuery(GET_CONTENT_ID_FROM_ARTIFACT_ID + this.solrObjectId);
- ResultSet resultSet = executeQuery.getResultSet();) {
- if (resultSet.next()) {
- contentID = resultSet.getLong("obj_id");
- } else {
- throw new TskCoreException("Failed to get obj_id for artifact with artifact_id =" + this.solrObjectId + ". No matching artifact was found.");
- }
- } catch (SQLException ex) {
- throw new TskCoreException("Error getting obj_id for artifact with artifact_id =" + this.solrObjectId, ex);
- }
- } else {
- //else the object id is for content.
- contentID = this.solrObjectId;
- }
}
String getHit() {
@@ -112,7 +83,7 @@ class KeywordHit implements Comparable {
}
String getSolrDocumentId() {
- return this.solrDocumentId;
+ return Long.toString(solrObjectId) + Server.CHUNK_ID_SEPARATOR + Long.toString(chunkId);
}
long getSolrObjectId() {
@@ -131,8 +102,36 @@ class KeywordHit implements Comparable {
return this.snippet;
}
- long getContentID() {
- return this.contentID;
+ /**
+ * Get the content id associated with the content underlying hit.
+ * For hits on files this will be the same as the object id associated
+ * with the file. For hits on artifacts we look up the id of the object
+ * that produced the artifact.
+ *
+ * @return The id of the underlying content associated with the hit.
+ * @throws TskCoreException If there is a problem getting the underlying
+ * content associated with a hit on the text of an
+ * artifact.
+ */
+ long getContentID() throws TskCoreException {
+ if (isArtifactHit()) {
+ // If the hit was in an artifact, look up the source content for the artifact.
+ SleuthkitCase caseDb = Case.getCurrentCase().getSleuthkitCase();
+ try (SleuthkitCase.CaseDbQuery executeQuery =
+ caseDb.executeQuery(GET_CONTENT_ID_FROM_ARTIFACT_ID + this.solrObjectId);
+ ResultSet resultSet = executeQuery.getResultSet();) {
+ if (resultSet.next()) {
+ return resultSet.getLong("obj_id");
+ } else {
+ throw new TskCoreException("Failed to get obj_id for artifact with artifact_id =" + this.solrObjectId + ". No matching artifact was found.");
+ }
+ } catch (SQLException ex) {
+ throw new TskCoreException("Error getting obj_id for artifact with artifact_id =" + this.solrObjectId, ex);
+ }
+ } else {
+ //else the object id is for content.
+ return this.solrObjectId;
+ }
}
/**
@@ -141,7 +140,8 @@ class KeywordHit implements Comparable {
* @return
*/
boolean isArtifactHit() {
- return hitOnArtifact;
+ // artifacts have negative obj ids
+ return this.solrObjectId < 0;
}
/**
@@ -150,7 +150,7 @@ class KeywordHit implements Comparable {
* @return The artifact whose indexed text this hit is in.
*/
Optional getArtifactID() {
- if (hitOnArtifact) {
+ if (isArtifactHit()) {
return Optional.of(solrObjectId);
} else {
return Optional.empty();
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java
index 8e820b4c74..c34e672a1c 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 JPanel
+ * subclass have not been constructed yet, since this panel's
+ * constructor has not been called yet.
+ */
+ if (null != listsPanel) {
+ listsPanel.addPropertyChangeListener(l);
+ }
+ if (null != languagesPanel) {
+ languagesPanel.addPropertyChangeListener(l);
+ }
+ if (null != generalPanel) {
+ generalPanel.addPropertyChangeListener(l);
+ }
}
@Override
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/RegexQuery.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/RegexQuery.java
index 0927b68d6c..6734cbf47d 100755
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/RegexQuery.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/RegexQuery.java
@@ -226,6 +226,8 @@ final class RegexQuery implements KeywordSearchQuery {
private List createKeywordHits(SolrDocument solrDoc) throws TskCoreException {
+ final HashMap keywordsFoundInThisDocument = new HashMap<>();
+
List hits = new ArrayList<>();
final String docId = solrDoc.getFieldValue(Server.Schema.ID.toString()).toString();
final Integer chunkSize = (Integer) solrDoc.getFieldValue(Server.Schema.CHUNK_SIZE.toString());
@@ -273,6 +275,23 @@ final class RegexQuery implements KeywordSearchQuery {
hit = hit.replaceAll("[^0-9]$", "");
}
+ /**
+ * The use of String interning is an optimization to ensure
+ * that we reuse the same keyword hit String object across
+ * all hits. Even though we benefit from G1GC String
+ * deduplication, the overhead associated with creating a
+ * new String object for every KeywordHit can be significant
+ * when the number of hits gets large.
+ */
+ hit = hit.intern();
+
+ // We will only create one KeywordHit instance per document for
+ // a given hit.
+ if (keywordsFoundInThisDocument.containsKey(hit)) {
+ continue;
+ }
+ keywordsFoundInThisDocument.put(hit, hit);
+
if (artifactAttributeType == null) {
hits.add(new KeywordHit(docId, makeSnippet(content, hitMatcher, hit), hit));
} else {
@@ -303,7 +322,7 @@ final class RegexQuery implements KeywordSearchQuery {
final String group = ccnMatcher.group("ccn");
if (CreditCardValidator.isValidCCN(group)) {
hits.add(new KeywordHit(docId, makeSnippet(content, hitMatcher, hit), hit));
- };
+ }
}
}
@@ -316,8 +335,6 @@ final class RegexQuery implements KeywordSearchQuery {
}
}
- } catch (TskCoreException ex) {
- throw ex;
} catch (Throwable error) {
/*
* NOTE: Matcher.find() is known to throw StackOverflowError in rare
@@ -463,7 +480,7 @@ final class RegexQuery implements KeywordSearchQuery {
if (hit.isArtifactHit()) {
LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for artifact keyword hit: term = %s, snippet = '%s', artifact id = %d", foundKeyword.getSearchTerm(), hit.getSnippet(), hit.getArtifactID().get())); //NON-NLS
} else {
- LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for content keyword hit: term = %s, snippet = '%s', object id = %d", foundKeyword.getSearchTerm(), hit.getSnippet(), hit.getContentID())); //NON-NLS
+ LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for content keyword hit: term = %s, snippet = '%s', object id = %d", foundKeyword.getSearchTerm(), hit.getSnippet(), hit.getSolrObjectId())); //NON-NLS
}
return null;
}
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TermsComponentQuery.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TermsComponentQuery.java
index ab647ec048..68c510a7e3 100755
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TermsComponentQuery.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TermsComponentQuery.java
@@ -381,7 +381,7 @@ final class TermsComponentQuery implements KeywordSearchQuery {
if (hit.isArtifactHit()) {
LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for artifact keyword hit: term = %s, snippet = '%s', artifact id = %d", searchTerm, hit.getSnippet(), hit.getArtifactID().get())); //NON-NLS
} else {
- LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for content keyword hit: term = %s, snippet = '%s', object id = %d", searchTerm, hit.getSnippet(), hit.getContentID())); //NON-NLS
+ LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for content keyword hit: term = %s, snippet = '%s', object id = %d", searchTerm, hit.getSnippet(), hit.getSolrObjectId())); //NON-NLS
}
return null;
}
diff --git a/developers/README.txt b/developers/README.txt
index ce28add84d..61fcac0963 100755
--- a/developers/README.txt
+++ b/developers/README.txt
@@ -1,3 +1,6 @@
+CURRENTLY NOT WORKING for NETBEANS IDE 8.2,
+NETBEANS BUG REPORT: https://netbeans.org/bugzilla/show_bug.cgi?id=271811
+
Common NetBeans IDE settings for the Autopsy project are stored here.
All contributors are kindly asked to use these settings.
@@ -7,11 +10,11 @@ Select Options to Import dialog. Push the Browse... button to pop up a file
chooser. Select ~\autopsy\developers\netbeans_ide_formatting_settings.zip.
NetBeans IDE will require a restart for the settings to take effect. Formatting
can be done by selecting Source, Format (Alt + Shift + F).
-2. To make Java code hygiene hints (lint) settings, copy the entire contents of
-~\autopsy\developers\netbeans_ide_java_hint_settings to the hint/default
-subdirectory of your user settings directory for the IDE. For Windows, this is
-~\AppData\Roaming\NetBeans\8.2\config\Preferences\org\netbeans\modules\java\hints
-\default. Restart the IDE.
+2. To make Java code hygiene hints (lint) settings, select Tools,
+Options, Editor tab, Hints tab. Push the Import... button to pop up the
+Select Options to Import dialog. Push the Browse... button to pop up a file
+chooser. Select ~\autopsy\developers\netbeans_ide_editor_settings.zip.
+NetBeans IDE will require a restart for the settings to take effect
diff --git a/developers/netbeans_ide_java_editor_settings.zip b/developers/netbeans_ide_java_editor_settings.zip
new file mode 100755
index 0000000000..102d366250
Binary files /dev/null and b/developers/netbeans_ide_java_editor_settings.zip differ
diff --git a/developers/netbeans_ide_java_hint_settings/Braces_DO_WHILE_LOOP.properties b/developers/netbeans_ide_java_hint_settings/Braces_DO_WHILE_LOOP.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/Braces_DO_WHILE_LOOP.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/Braces_FOR_LOOP.properties b/developers/netbeans_ide_java_hint_settings/Braces_FOR_LOOP.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/Braces_FOR_LOOP.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/Braces_IF.properties b/developers/netbeans_ide_java_hint_settings/Braces_IF.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/Braces_IF.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/Braces_WHILE_LOOP.properties b/developers/netbeans_ide_java_hint_settings/Braces_WHILE_LOOP.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/Braces_WHILE_LOOP.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/EmptyStatements_IF.properties b/developers/netbeans_ide_java_hint_settings/EmptyStatements_IF.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/EmptyStatements_IF.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/Imports_STAR.properties b/developers/netbeans_ide_java_hint_settings/Imports_STAR.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/Imports_STAR.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/Javac_DEPRECATED.properties b/developers/netbeans_ide_java_hint_settings/Javac_DEPRECATED.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/Javac_DEPRECATED.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/Javac_DIVISION_BY_ZERO.properties b/developers/netbeans_ide_java_hint_settings/Javac_DIVISION_BY_ZERO.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/Javac_DIVISION_BY_ZERO.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/Javac_EMPTY_STATEMENT_AFTER_IF.properties b/developers/netbeans_ide_java_hint_settings/Javac_EMPTY_STATEMENT_AFTER_IF.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/Javac_EMPTY_STATEMENT_AFTER_IF.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/Javac_FALLTHROUGH.properties b/developers/netbeans_ide_java_hint_settings/Javac_FALLTHROUGH.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/Javac_FALLTHROUGH.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/Javac_FINALLY.properties b/developers/netbeans_ide_java_hint_settings/Javac_FINALLY.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/Javac_FINALLY.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/Javac_OVERRIDES.properties b/developers/netbeans_ide_java_hint_settings/Javac_OVERRIDES.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/Javac_OVERRIDES.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/Javac_RAWTYPES.properties b/developers/netbeans_ide_java_hint_settings/Javac_RAWTYPES.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/Javac_RAWTYPES.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/Javac_SERIALIZATION.properties b/developers/netbeans_ide_java_hint_settings/Javac_SERIALIZATION.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/Javac_SERIALIZATION.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/Javac_UNCHECKED.properties b/developers/netbeans_ide_java_hint_settings/Javac_UNCHECKED.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/Javac_UNCHECKED.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/Javac_UNNECESSARY_CAST.properties b/developers/netbeans_ide_java_hint_settings/Javac_UNNECESSARY_CAST.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/Javac_UNNECESSARY_CAST.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/MAVEN_SEARCH_HINT.properties b/developers/netbeans_ide_java_hint_settings/MAVEN_SEARCH_HINT.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/MAVEN_SEARCH_HINT.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.ConsistentAccessType.properties b/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.ConsistentAccessType.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.ConsistentAccessType.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.HasNoArgConstructor.properties b/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.HasNoArgConstructor.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.HasNoArgConstructor.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.IdClassOverridesEqualsAndHashCode.properties b/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.IdClassOverridesEqualsAndHashCode.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.IdClassOverridesEqualsAndHashCode.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.IdDefinedInHierarchy.properties b/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.IdDefinedInHierarchy.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.IdDefinedInHierarchy.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.JPAAnnotsOnlyOnAccesor.properties b/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.JPAAnnotsOnlyOnAccesor.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.JPAAnnotsOnlyOnAccesor.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.JPQLValidation.properties b/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.JPQLValidation.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.JPQLValidation.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.LegalCombinationOfAnnotations.properties b/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.LegalCombinationOfAnnotations.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.LegalCombinationOfAnnotations.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.NoIdClassOnEntitySubclass.properties b/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.NoIdClassOnEntitySubclass.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.NoIdClassOnEntitySubclass.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.NonFinalClass.properties b/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.NonFinalClass.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.NonFinalClass.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.OnlyEntityOrMappedSuperclassCanUseIdClass.properties b/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.OnlyEntityOrMappedSuperclassCanUseIdClass.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.OnlyEntityOrMappedSuperclassCanUseIdClass.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.PersistenceUnitPresent.properties b/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.PersistenceUnitPresent.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.PersistenceUnitPresent.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.PublicClass.properties b/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.PublicClass.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.PublicClass.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.QueriesProperlyDefined.properties b/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.QueriesProperlyDefined.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.QueriesProperlyDefined.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.SerializableClass.properties b/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.SerializableClass.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.SerializableClass.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.TopLevelClass.properties b/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.TopLevelClass.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.TopLevelClass.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.UniqueEntityName.properties b/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.UniqueEntityName.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.UniqueEntityName.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.ValidAttributes.properties b/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.ValidAttributes.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.ValidAttributes.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.ValidPrimaryTableName.properties b/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.ValidPrimaryTableName.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/o.n.m.j2ee.jpa.verification.ValidPrimaryTableName.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.AssignResultToVariable.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.AssignResultToVariable.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.AssignResultToVariable.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.AssignmentIssues.assignmentToCatchBlockParameter.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.AssignmentIssues.assignmentToCatchBlockParameter.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.AssignmentIssues.assignmentToCatchBlockParameter.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.AssignmentIssues.assignmentToForLoopParam.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.AssignmentIssues.assignmentToForLoopParam.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.AssignmentIssues.assignmentToForLoopParam.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.AssignmentIssues.assignmentToMethodParam.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.AssignmentIssues.assignmentToMethodParam.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.AssignmentIssues.assignmentToMethodParam.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.AssignmentIssues.incrementDecrementUsed.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.AssignmentIssues.incrementDecrementUsed.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.AssignmentIssues.incrementDecrementUsed.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.AssignmentIssues.nestedAssignment.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.AssignmentIssues.nestedAssignment.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.AssignmentIssues.nestedAssignment.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.AssignmentIssues.replaceAssignWithOpAssign.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.AssignmentIssues.replaceAssignWithOpAssign.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.AssignmentIssues.replaceAssignWithOpAssign.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.classMayBeInterface.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.classMayBeInterface.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.classMayBeInterface.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.finalClass.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.finalClass.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.finalClass.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.finalMethodInFinalClass.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.finalMethodInFinalClass.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.finalMethodInFinalClass.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.finalPrivateMethod.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.finalPrivateMethod.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.finalPrivateMethod.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.markerInterface.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.markerInterface.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.markerInterface.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.multipleTopLevelClassesInFile.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.multipleTopLevelClassesInFile.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.multipleTopLevelClassesInFile.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.noopMethodInAbstractClass.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.noopMethodInAbstractClass.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.noopMethodInAbstractClass.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.protectedMemberInFinalClass.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.protectedMemberInFinalClass.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.protectedMemberInFinalClass.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.publicConstructorInNonPublicClass.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.publicConstructorInNonPublicClass.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ClassStructure.publicConstructorInNonPublicClass.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.EmptyCancelForCancellableTask.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.EmptyCancelForCancellableTask.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.EmptyCancelForCancellableTask.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ExportNonAccessibleElement.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ExportNonAccessibleElement.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ExportNonAccessibleElement.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.IllegalInstanceOf.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.IllegalInstanceOf.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.IllegalInstanceOf.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.IncompatibleMask.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.IncompatibleMask.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.IncompatibleMask.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.OrganizeImports.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.OrganizeImports.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.OrganizeImports.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.OrganizeMembers.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.OrganizeMembers.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.OrganizeMembers.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.PointlessBitwiseExpression.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.PointlessBitwiseExpression.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.PointlessBitwiseExpression.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ShiftOutOfRange.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ShiftOutOfRange.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.ShiftOutOfRange.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.StaticImport.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.StaticImport.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.StaticImport.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.SuspiciousNamesCombination.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.SuspiciousNamesCombination.properties
deleted file mode 100755
index cec1caef1a..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.SuspiciousNamesCombination.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-enabled=true
-groups=x, width|y, height
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.SystemOut.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.SystemOut.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.SystemOut.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.UtilityClass_1.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.UtilityClass_1.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.UtilityClass_1.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.UtilityClass_2.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.UtilityClass_2.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.UtilityClass_2.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.bugs.BroadCatchBlock.broadCatch.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.bugs.BroadCatchBlock.broadCatch.properties
deleted file mode 100755
index f422278785..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.bugs.BroadCatchBlock.broadCatch.properties
+++ /dev/null
@@ -1,4 +0,0 @@
-catch.common=true
-catch.umbrella=false
-catch.umbrella.types=java.io.IOException, java.sql.SqlException
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.bugs.CloneAndCloneable.cloneInNonCloneableClass.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.bugs.CloneAndCloneable.cloneInNonCloneableClass.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.bugs.CloneAndCloneable.cloneInNonCloneableClass.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.bugs.CloneAndCloneable.cloneableWithoutClone.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.bugs.CloneAndCloneable.cloneableWithoutClone.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.bugs.CloneAndCloneable.cloneableWithoutClone.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ClassEncapsulation.packageCls.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ClassEncapsulation.packageCls.properties
deleted file mode 100755
index 65e0f4d095..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ClassEncapsulation.packageCls.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-allow.enums=false
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ClassEncapsulation.protectedCls.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ClassEncapsulation.protectedCls.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ClassEncapsulation.protectedCls.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ClassEncapsulation.publicCls.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ClassEncapsulation.publicCls.properties
deleted file mode 100755
index 65e0f4d095..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ClassEncapsulation.publicCls.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-allow.enums=false
-enabled=false
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.FieldEncapsulation.packageField.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.FieldEncapsulation.packageField.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.FieldEncapsulation.packageField.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.FieldEncapsulation.privateField.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.FieldEncapsulation.privateField.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.FieldEncapsulation.privateField.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.FieldEncapsulation.protectedField.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.FieldEncapsulation.protectedField.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.FieldEncapsulation.protectedField.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.FieldEncapsulation.publicField.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.FieldEncapsulation.publicField.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.FieldEncapsulation.publicField.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ParamEncapsulation.array.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ParamEncapsulation.array.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ParamEncapsulation.array.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ParamEncapsulation.collection.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ParamEncapsulation.collection.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ParamEncapsulation.collection.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ParamEncapsulation.date.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ParamEncapsulation.date.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ParamEncapsulation.date.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ReturnEncapsulation.array.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ReturnEncapsulation.array.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ReturnEncapsulation.array.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ReturnEncapsulation.collection.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ReturnEncapsulation.collection.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ReturnEncapsulation.collection.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ReturnEncapsulation.date.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ReturnEncapsulation.date.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.encapsulation.ReturnEncapsulation.date.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.finalize.FinalizeNotProtected.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.finalize.FinalizeNotProtected.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.finalize.FinalizeNotProtected.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.jdk.AddUnderscores.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.jdk.AddUnderscores.properties
deleted file mode 100755
index 8e183448b6..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.jdk.AddUnderscores.properties
+++ /dev/null
@@ -1,4 +0,0 @@
-also-with-underscores=false
-size-binary=4
-size-decimal=3
-size-hexadecimal=4
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.jdk.mapreduce.ForLoopToFunctionalHint.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.jdk.mapreduce.ForLoopToFunctionalHint.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.jdk.mapreduce.ForLoopToFunctionalHint.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.perf.InitialCapacity.stringBuilder.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.perf.InitialCapacity.stringBuilder.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.perf.InitialCapacity.stringBuilder.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.perf.Tiny.collectionsToArray.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.perf.Tiny.collectionsToArray.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.perf.Tiny.collectionsToArray.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.perf.Tiny.constantIntern.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.perf.Tiny.constantIntern.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.perf.Tiny.constantIntern.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.perf.Tiny.getClassInsteadOfDotClass.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.perf.Tiny.getClassInsteadOfDotClass.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.perf.Tiny.getClassInsteadOfDotClass.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.perf.Tiny.lengthOneStringIndexOf.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.perf.Tiny.lengthOneStringIndexOf.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.perf.Tiny.lengthOneStringIndexOf.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.perf.Tiny.stringEqualsEmpty.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.perf.Tiny.stringEqualsEmpty.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.perf.Tiny.stringEqualsEmpty.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.suggestions.ConstantNameHint.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.suggestions.ConstantNameHint.properties
deleted file mode 100755
index 90d01d9f5d..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.suggestions.ConstantNameHint.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-immutableClasses=
-maxLength=35
-minLength=0
-namePattern=[A-Z]([A-Z\\d_]*[A-Z\\d])?
-onlyCheckImmutables=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.suggestions.TooStrongCast.broadTypeCast.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.suggestions.TooStrongCast.broadTypeCast.properties
deleted file mode 100755
index 46ba29290c..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.hints.suggestions.TooStrongCast.broadTypeCast.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=true
diff --git a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.testrunner.ui.hints.CreateTestClassHint.properties b/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.testrunner.ui.hints.CreateTestClassHint.properties
deleted file mode 100755
index 541deecb31..0000000000
--- a/developers/netbeans_ide_java_hint_settings/org.netbeans.modules.java.testrunner.ui.hints.CreateTestClassHint.properties
+++ /dev/null
@@ -1 +0,0 @@
-enabled=false