From 1475574ace4e25477a43679249d57cac3b7c96b5 Mon Sep 17 00:00:00 2001 From: Karl Mortensen Date: Tue, 26 May 2015 10:08:05 -0400 Subject: [PATCH 1/9] framework to warn user of issues without spamming them --- .../autopsy/casemodule/Bundle.properties | 4 + .../sleuthkit/autopsy/casemodule/Case.java | 104 +++++++++++++++++- 2 files changed, 107 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index cdbed0aa1f..8adb686daf 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -137,6 +137,7 @@ Case.createCaseDir.exception.cantCreateReportsDir=Could not create reports outpu Case.createCaseDir.exception.gen=Could not create case directory\: {0} Case.OpenEventChannel.FailPopup.ErrMsg=Failed to connect to any other nodes that may be collaborating on this case. Case.OpenEventChannel.FailPopup.Title=Connection Failure +Case.GetCaseTypeGivenPath.Failure=Unable to get case type CaseDeleteAction.closeConfMsg.text=Are you sure want to close and delete this case? \n\ Case Name\: {0}\n\ Case Directory\: {1} @@ -151,6 +152,9 @@ CaseOpenAction.msgDlg.fileNotExist.title=Error CaseOpenAction.msgDlg.cantOpenCase.msg=Error\: could not open the case in folder {0}\: {1} CaseOpenAction.msgDlg.cantOpenCase.title=Error CaseCreateAction.msgDlg.cantCreateCase.msg=Cannot create case +CaseIntervalErrorReport.NewIssues=new issues +CaseIntervalErrorReport.TotalIssues=total issues +CaseIntervalErrorReport.ErrorText=Database Connection Error CasePropertiesAction.window.title=Case Properties CasePropertiesForm.updateCaseName.msgDlg.empty.msg=The caseName cannot be empty. CasePropertiesForm.updateCaseName.msgDlg.empty.title=Error diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 33a2b00386..f10ad14fb4 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -43,6 +43,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; +import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.openide.util.actions.CallableSystemAction; @@ -70,7 +71,7 @@ import org.sleuthkit.datamodel.SleuthkitJNI.CaseDbHandle.AddImageProcess; * case. */ @SuppressWarnings("deprecation") // TODO: Remove this when ErrorObserver is replaced. -public class Case implements SleuthkitCase.ErrorObserver { +public class Case implements SleuthkitCase.ErrorObserver, SleuthkitCase.SleuthkitCaseErrorObserver { private static final String autopsyVer = Version.getVersion(); // current version of autopsy. Change it when the version is changed private static final String EVENT_CHANNEL_NAME = "%s-Case-Events"; @@ -88,6 +89,10 @@ public class Case implements SleuthkitCase.ErrorObserver { */ private static final AutopsyEventPublisher eventPublisher = new AutopsyEventPublisher(); + private final IntervalErrorReportData databaseErrorReporter = new IntervalErrorReportData( + 60, // No less than 60 seconds between warnings for database errors + NbBundle.getMessage(Case.class, "CaseIntervalErrorReport.ErrorText")); + /** * Events that the case module will fire. Event listeners can get the event * name by using String returned by toString() method on a specific event. @@ -224,6 +229,7 @@ public class Case implements SleuthkitCase.ErrorObserver { */ private void init() { db.addErrorObserver(this); + db.addSleuthkitCaseErrorObserver(this); } /** @@ -747,6 +753,24 @@ public class Case implements SleuthkitCase.ErrorObserver { return this.caseType; } + /** + * Get the case type within an .aut file. Defaults to single-user case if + * there is a problem. + * + * @param thePath the path to the file, example: C:\folder\case.aut + * @return The case type contained in the .aut file. + */ + public static CaseType getCaseType(Path thePath) { + try { + XMLCaseManagement xmlcm = new XMLCaseManagement(); + xmlcm.open(thePath.toString()); + return xmlcm.getCaseType(); + } catch (CaseActionException ex) { + logger.log(Level.SEVERE, NbBundle.getMessage(Case.class, "Case.GetCaseTypeGivenPath.Failure"), ex); // NON-NLS + return CaseType.SINGLE_USER_CASE; + } + } + /** * Gets the full path to the temp directory of this case. Will create it if * it does not already exist. @@ -1344,6 +1368,84 @@ public class Case implements SleuthkitCase.ErrorObserver { MessageNotifyUtil.Notify.error(context, errorMessage); } + @Override + public void receiveSleuthkitCaseError(SleuthkitCase.SleuthkitCaseErrorObserver.TypeOfError typeOfError, String errorMessage) { + if (typeOfError == SleuthkitCase.SleuthkitCaseErrorObserver.TypeOfError.DATABASE) { + databaseErrorReporter.addProblems(1, errorMessage); + } + } + + /** + * This class enables capturing errors and batching them for reporting on a + * no-more-than-x number of seconds basis. When created, you specify what + * type of error it will be batching, and the minimum time between user + * notifications. When the time between notifications has expired, the next + * error encountered will cause a report to be shown to the user. + */ + public class IntervalErrorReportData { + + private long newProblems; + private long totalProblems; + private boolean firstErrorSent; + private long lastReportedDate; + private final int milliSecondsBetweenReports; + private final String message; + + /** + * Create a new IntervalErrorReprotData instance. + * + * @param secondsBetweenReports Minimum number of seconds between + * reports. It will not warn more frequently than this. + * @param message The message that will be shown when warning the user + */ + public IntervalErrorReportData(int secondsBetweenReports, String message) { + this.newProblems = 0; + this.totalProblems = 0; + this.firstErrorSent = false; + this.lastReportedDate = System.currentTimeMillis(); + this.milliSecondsBetweenReports = secondsBetweenReports * 1000; // convert to milliseconds + this.message = message; + } + + /** + * Call this to add problems to the class. When the time threshold is + * met (or if this is the first problem encountered), a warning will be + * shown to the user. + * + * @param newProblems the newProblems to set + * @param errorMessage the message for this specific error + */ + public void addProblems(long newProblems, String errorMessage) { + this.newProblems += newProblems; + this.totalProblems += newProblems; + + if (firstErrorSent == false) { + firstErrorSent = true; + this.lastReportedDate = System.currentTimeMillis(); + MessageNotifyUtil.Notify.error(message, errorMessage + " " + + this.newProblems + " " + + NbBundle.getMessage(Case.class, "CaseIntervalErrorReport.NewIssues") + + " " + this.totalProblems + " " + + NbBundle.getMessage(Case.class, "CaseIntervalErrorReport.TotalIssues") + + "."); + + this.newProblems = 0; + } + long currentTimeStamp = System.currentTimeMillis(); + if ((currentTimeStamp - lastReportedDate) > milliSecondsBetweenReports) { + this.lastReportedDate = currentTimeStamp; + MessageNotifyUtil.Notify.error(message, errorMessage + " " + + this.newProblems + " " + + NbBundle.getMessage(Case.class, "CaseIntervalErrorReport.NewIssues") + + " " + this.totalProblems + " " + + NbBundle.getMessage(Case.class, "CaseIntervalErrorReport.TotalIssues") + + "."); + this.newProblems = 0; + } + } + } + + /** * Adds a report to the case. * From df2f8cea7f08c01d231d145dbc4f9511bb76f339 Mon Sep 17 00:00:00 2001 From: Karl Mortensen Date: Wed, 27 May 2015 16:59:43 -0400 Subject: [PATCH 2/9] interim update --- Core/src/org/sleuthkit/autopsy/casemodule/Case.java | 9 +++++++-- .../autopsy/casemodule/NewCaseVisualPanel1.java | 2 +- .../autopsy/casemodule/NewCaseWizardAction.java | 2 +- Core/src/org/sleuthkit/autopsy/core/UserPreferences.java | 2 +- .../autopsy/corecomponents/MultiUserSettingsPanel.java | 4 ++-- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index f10ad14fb4..3d697d7de0 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -76,7 +76,8 @@ public class Case implements SleuthkitCase.ErrorObserver, SleuthkitCase.Sleuthki private static final String autopsyVer = Version.getVersion(); // current version of autopsy. Change it when the version is changed private static final String EVENT_CHANNEL_NAME = "%s-Case-Events"; private static String appName = null; - + private static boolean firstTime=true; + /** * Name for the property that determines whether to show the dialog at * startup @@ -229,7 +230,11 @@ public class Case implements SleuthkitCase.ErrorObserver, SleuthkitCase.Sleuthki */ private void init() { db.addErrorObserver(this); - db.addSleuthkitCaseErrorObserver(this); + if(firstTime) + { + firstTime=false; + db.addSleuthkitCaseErrorObserver(this); + } } /** diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseVisualPanel1.java b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseVisualPanel1.java index 82584797f1..4dd63ca497 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseVisualPanel1.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseVisualPanel1.java @@ -49,7 +49,7 @@ final class NewCaseVisualPanel1 extends JPanel implements DocumentListener { caseNameTextField.getDocument().addDocumentListener(this); caseParentDirTextField.getDocument().addDocumentListener(this); CaseDbConnectionInfo info = UserPreferences.getDatabaseConnectionInfo(); - if (info.getDbType() == DbType.UNKNOWN) { + if (info.getDbType() == DbType.SQLITE) { rbSingleUserCase.setSelected(true); rbSingleUserCase.setEnabled(false); rbMultiUserCase.setEnabled(false); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java index 96e9a40442..e187937f43 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java @@ -99,7 +99,7 @@ import org.sleuthkit.datamodel.TskData.DbType; //TODO fix for local CaseType currentCaseType = CaseType.fromString(ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, ModuleSettings.CURRENT_CASE_TYPE)); CaseDbConnectionInfo info = UserPreferences.getDatabaseConnectionInfo(); - if ((currentCaseType==CaseType.SINGLE_USER_CASE) || ((info.getDbType() != DbType.UNKNOWN) && info.settingsValid())) { + if ((currentCaseType==CaseType.SINGLE_USER_CASE) || ((info.getDbType() != DbType.SQLITE) && info.settingsValid())) { AddImageAction addImageAction = SystemAction.get(AddImageAction.class); addImageAction.actionPerformed(null); } else { diff --git a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java index 3051ca840a..eb8da0234c 100755 --- a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java +++ b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java @@ -111,7 +111,7 @@ public final class UserPreferences { try { dbType = DbType.valueOf(preferences.get(EXTERNAL_DATABASE_TYPE, "UNKOWN")); } catch (Exception ex) { - dbType = DbType.UNKNOWN; + dbType = DbType.SQLITE; } return new CaseDbConnectionInfo( preferences.get(EXTERNAL_DATABASE_HOSTNAME_OR_IP, ""), diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.java index 4efe297203..a5c586ae72 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.java @@ -398,7 +398,7 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { tbIndexingServerPort.setText(indexingServerPort); } - if (dbInfo.getDbType() == DbType.UNKNOWN) { + if (dbInfo.getDbType() == DbType.SQLITE) { cbEnableMultiUser.setSelected(false); } else { cbEnableMultiUser.setSelected(true); @@ -420,7 +420,7 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { void store() { - DbType dbType = DbType.UNKNOWN; + DbType dbType = DbType.SQLITE; if (cbEnableMultiUser.isSelected()) { dbType = DbType.POSTGRESQL; From c7d9cedf2908941cfd1719753f587097aae5961c Mon Sep 17 00:00:00 2001 From: Karl Mortensen Date: Mon, 1 Jun 2015 13:54:50 -0400 Subject: [PATCH 3/9] remove vestigial method --- .../org/sleuthkit/autopsy/casemodule/Case.java | 18 ------------------ .../netbeans/core/startup/Bundle.properties | 2 +- .../core/windows/view/ui/Bundle.properties | 2 +- 3 files changed, 2 insertions(+), 20 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 3d697d7de0..7e33e90237 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -758,24 +758,6 @@ public class Case implements SleuthkitCase.ErrorObserver, SleuthkitCase.Sleuthki return this.caseType; } - /** - * Get the case type within an .aut file. Defaults to single-user case if - * there is a problem. - * - * @param thePath the path to the file, example: C:\folder\case.aut - * @return The case type contained in the .aut file. - */ - public static CaseType getCaseType(Path thePath) { - try { - XMLCaseManagement xmlcm = new XMLCaseManagement(); - xmlcm.open(thePath.toString()); - return xmlcm.getCaseType(); - } catch (CaseActionException ex) { - logger.log(Level.SEVERE, NbBundle.getMessage(Case.class, "Case.GetCaseTypeGivenPath.Failure"), ex); // NON-NLS - return CaseType.SINGLE_USER_CASE; - } - } - /** * Gets the full path to the temp directory of this case. Will create it if * it does not already exist. diff --git a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties index 256e682850..a33026a567 100644 --- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Tue, 28 Apr 2015 18:19:58 -0400 +#Mon, 01 Jun 2015 13:48:02 -0400 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=314 SPLASH_WIDTH=538 diff --git a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties index b8a2cebc1c..9634a11591 100644 --- a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties +++ b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Tue, 28 Apr 2015 18:19:58 -0400 +#Mon, 01 Jun 2015 13:48:02 -0400 CTL_MainWindow_Title=Autopsy 3.1.2 CTL_MainWindow_Title_No_Project=Autopsy 3.1.2 From a239cbd49037bfd01427baaa695357942387a906 Mon Sep 17 00:00:00 2001 From: Karl Mortensen Date: Mon, 1 Jun 2015 13:57:30 -0400 Subject: [PATCH 4/9] remove vestigial method --- .../core/core.jar/org/netbeans/core/startup/Bundle.properties | 2 +- .../org/netbeans/core/windows/view/ui/Bundle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties index a33026a567..256e682850 100644 --- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Mon, 01 Jun 2015 13:48:02 -0400 +#Tue, 28 Apr 2015 18:19:58 -0400 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=314 SPLASH_WIDTH=538 diff --git a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties index 9634a11591..b8a2cebc1c 100644 --- a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties +++ b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Mon, 01 Jun 2015 13:48:02 -0400 +#Tue, 28 Apr 2015 18:19:58 -0400 CTL_MainWindow_Title=Autopsy 3.1.2 CTL_MainWindow_Title_No_Project=Autopsy 3.1.2 From 87d4747a4cf27cec5935873f7dfd46f7535b6bb9 Mon Sep 17 00:00:00 2001 From: Karl Mortensen Date: Mon, 1 Jun 2015 14:18:56 -0400 Subject: [PATCH 5/9] static --- Core/src/org/sleuthkit/autopsy/casemodule/Case.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 7e33e90237..f11259dd89 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -233,7 +233,7 @@ public class Case implements SleuthkitCase.ErrorObserver, SleuthkitCase.Sleuthki if(firstTime) { firstTime=false; - db.addSleuthkitCaseErrorObserver(this); + SleuthkitCase.addSleuthkitCaseErrorObserver(this); } } From 8f90010ab2d8acf26307619e9c61ac33518bebbd Mon Sep 17 00:00:00 2001 From: Karl Mortensen Date: Tue, 2 Jun 2015 17:14:25 -0400 Subject: [PATCH 6/9] warn nicely again --- .../autopsy/casemodule/Bundle.properties | 6 +- .../sleuthkit/autopsy/casemodule/Case.java | 99 +---------------- .../casemodule/IntervalErrorReportData.java | 103 ++++++++++++++++++ 3 files changed, 110 insertions(+), 98 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/IntervalErrorReportData.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index e0836e3168..4b6bbd2ac9 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -152,9 +152,9 @@ CaseOpenAction.msgDlg.fileNotExist.title=Error CaseOpenAction.msgDlg.cantOpenCase.msg=Error\: could not open the case in folder {0}\: {1} CaseOpenAction.msgDlg.cantOpenCase.title=Error CaseCreateAction.msgDlg.cantCreateCase.msg=Cannot create case -CaseIntervalErrorReport.NewIssues=new issues -CaseIntervalErrorReport.TotalIssues=total issues -CaseIntervalErrorReport.ErrorText=Database Connection Error +IntervalErrorReport.NewIssues=new issue(s) +IntervalErrorReport.TotalIssues=total issue(s) +IntervalErrorReport.ErrorText=Database Connection Error CasePropertiesAction.window.title=Case Properties CasePropertiesForm.updateCaseName.msgDlg.empty.msg=The caseName cannot be empty. CasePropertiesForm.updateCaseName.msgDlg.empty.title=Error diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index f11259dd89..b0f75171bb 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -43,7 +43,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; -import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.openide.util.actions.CallableSystemAction; @@ -71,12 +70,12 @@ import org.sleuthkit.datamodel.SleuthkitJNI.CaseDbHandle.AddImageProcess; * case. */ @SuppressWarnings("deprecation") // TODO: Remove this when ErrorObserver is replaced. -public class Case implements SleuthkitCase.ErrorObserver, SleuthkitCase.SleuthkitCaseErrorObserver { +public class Case { private static final String autopsyVer = Version.getVersion(); // current version of autopsy. Change it when the version is changed private static final String EVENT_CHANNEL_NAME = "%s-Case-Events"; private static String appName = null; - private static boolean firstTime=true; + private static IntervalErrorReportData tskErrorReporter = null; /** * Name for the property that determines whether to show the dialog at @@ -90,10 +89,6 @@ public class Case implements SleuthkitCase.ErrorObserver, SleuthkitCase.Sleuthki */ private static final AutopsyEventPublisher eventPublisher = new AutopsyEventPublisher(); - private final IntervalErrorReportData databaseErrorReporter = new IntervalErrorReportData( - 60, // No less than 60 seconds between warnings for database errors - NbBundle.getMessage(Case.class, "CaseIntervalErrorReport.ErrorText")); - /** * Events that the case module will fire. Event listeners can get the event * name by using String returned by toString() method on a specific event. @@ -229,12 +224,6 @@ public class Case implements SleuthkitCase.ErrorObserver, SleuthkitCase.Sleuthki * constructor. */ private void init() { - db.addErrorObserver(this); - if(firstTime) - { - firstTime=false; - SleuthkitCase.addSleuthkitCaseErrorObserver(this); - } } /** @@ -269,6 +258,8 @@ public class Case implements SleuthkitCase.ErrorObserver, SleuthkitCase.Sleuthki * */ private static void changeCase(Case newCase) { + // force static initialization of error reporter + tskErrorReporter = IntervalErrorReportData.getInstance(); // close the existing case Case oldCase = Case.currentCase; Case.currentCase = null; @@ -1350,88 +1341,6 @@ public class Case implements SleuthkitCase.ErrorObserver, SleuthkitCase.Sleuthki } } - @Override - public void receiveError(String context, String errorMessage) { - MessageNotifyUtil.Notify.error(context, errorMessage); - } - - @Override - public void receiveSleuthkitCaseError(SleuthkitCase.SleuthkitCaseErrorObserver.TypeOfError typeOfError, String errorMessage) { - if (typeOfError == SleuthkitCase.SleuthkitCaseErrorObserver.TypeOfError.DATABASE) { - databaseErrorReporter.addProblems(1, errorMessage); - } - } - - /** - * This class enables capturing errors and batching them for reporting on a - * no-more-than-x number of seconds basis. When created, you specify what - * type of error it will be batching, and the minimum time between user - * notifications. When the time between notifications has expired, the next - * error encountered will cause a report to be shown to the user. - */ - public class IntervalErrorReportData { - - private long newProblems; - private long totalProblems; - private boolean firstErrorSent; - private long lastReportedDate; - private final int milliSecondsBetweenReports; - private final String message; - - /** - * Create a new IntervalErrorReprotData instance. - * - * @param secondsBetweenReports Minimum number of seconds between - * reports. It will not warn more frequently than this. - * @param message The message that will be shown when warning the user - */ - public IntervalErrorReportData(int secondsBetweenReports, String message) { - this.newProblems = 0; - this.totalProblems = 0; - this.firstErrorSent = false; - this.lastReportedDate = System.currentTimeMillis(); - this.milliSecondsBetweenReports = secondsBetweenReports * 1000; // convert to milliseconds - this.message = message; - } - - /** - * Call this to add problems to the class. When the time threshold is - * met (or if this is the first problem encountered), a warning will be - * shown to the user. - * - * @param newProblems the newProblems to set - * @param errorMessage the message for this specific error - */ - public void addProblems(long newProblems, String errorMessage) { - this.newProblems += newProblems; - this.totalProblems += newProblems; - - if (firstErrorSent == false) { - firstErrorSent = true; - this.lastReportedDate = System.currentTimeMillis(); - MessageNotifyUtil.Notify.error(message, errorMessage + " " - + this.newProblems + " " - + NbBundle.getMessage(Case.class, "CaseIntervalErrorReport.NewIssues") - + " " + this.totalProblems + " " - + NbBundle.getMessage(Case.class, "CaseIntervalErrorReport.TotalIssues") - + "."); - - this.newProblems = 0; - } - long currentTimeStamp = System.currentTimeMillis(); - if ((currentTimeStamp - lastReportedDate) > milliSecondsBetweenReports) { - this.lastReportedDate = currentTimeStamp; - MessageNotifyUtil.Notify.error(message, errorMessage + " " - + this.newProblems + " " - + NbBundle.getMessage(Case.class, "CaseIntervalErrorReport.NewIssues") - + " " + this.totalProblems + " " - + NbBundle.getMessage(Case.class, "CaseIntervalErrorReport.TotalIssues") - + "."); - this.newProblems = 0; - } - } - } - /** * Adds a report to the case. diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/IntervalErrorReportData.java b/Core/src/org/sleuthkit/autopsy/casemodule/IntervalErrorReportData.java new file mode 100644 index 0000000000..9d9603b8e9 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/IntervalErrorReportData.java @@ -0,0 +1,103 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-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.casemodule; + +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; +import org.sleuthkit.datamodel.SleuthkitCase; + +/** + * This class enables capturing errors and batching them for reporting on a + * no-more-than-x number of seconds basis. When created, you specify what type + * of error it will be batching, and the minimum time between user + * notifications. When the time between notifications has expired, the next + * error encountered will cause a report to be shown to the user. + */ +public class IntervalErrorReportData implements SleuthkitCase.ErrorObserver { + + private static volatile IntervalErrorReportData instance; + private long newProblems; + private long totalProblems; + private long lastReportedDate; + private final int milliSecondsBetweenReports; + private final String message; + + /** + * Create a new IntervalErrorReprotData instance. + * + * @param secondsBetweenReports Minimum number of seconds between reports. + * It will not warn more frequently than this. + * @param message The message that will be shown when warning the user + */ + private IntervalErrorReportData(int secondsBetweenReports, String message) { + this.newProblems = 0; + this.totalProblems = 0; + this.lastReportedDate = 0; // arm the first warning by choosing zero + this.milliSecondsBetweenReports = secondsBetweenReports * 1000; // convert to milliseconds + this.message = message; + SleuthkitCase.addErrorObserver(this); + } + + /** + * Returns the singleton instance of this object + * + * @return the singleton instance of this object + */ + public static IntervalErrorReportData getInstance() { + if (instance == null) { + synchronized (IntervalErrorReportData.class) { + if (instance == null) { + instance = new IntervalErrorReportData(60, // No less than 60 seconds between warnings for errors + NbBundle.getMessage(Case.class, "IntervalErrorReport.ErrorText")); + } + } + } + return instance; + } + + /** + * Call this to add problems to the class. When the time threshold is met + * (or if this is the first problem encountered), a warning will be shown to + * the user. + * + * @param newProblems the newProblems to set + * @param ex the exception for this error + */ + public void addProblems(long newProblems, Exception ex) { + this.newProblems += newProblems; + this.totalProblems += newProblems; + + long currentTimeStamp = System.currentTimeMillis(); + if ((currentTimeStamp - lastReportedDate) > milliSecondsBetweenReports) { + this.lastReportedDate = currentTimeStamp; + MessageNotifyUtil.Notify.error(message, ex.getMessage() + " " + + this.newProblems + " " + + NbBundle.getMessage(IntervalErrorReportData.class, "IntervalErrorReport.NewIssues") + + " " + this.totalProblems + " " + + NbBundle.getMessage(IntervalErrorReportData.class, "IntervalErrorReport.TotalIssues") + + "."); + this.newProblems = 0; + } + } + + @Override + public void receiveError(Exception ex) { + addProblems(1, ex); + } +} From bede5b5e707d5457b8b9d1a523a70aa75406015e Mon Sep 17 00:00:00 2001 From: Karl Mortensen Date: Thu, 4 Jun 2015 10:08:55 -0400 Subject: [PATCH 7/9] remove deprecated --- Core/src/org/sleuthkit/autopsy/casemodule/Case.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index b0f75171bb..78c4f20c50 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -69,7 +69,6 @@ import org.sleuthkit.datamodel.SleuthkitJNI.CaseDbHandle.AddImageProcess; * open at a time. Use getCurrentCase() to retrieve the object for the current * case. */ -@SuppressWarnings("deprecation") // TODO: Remove this when ErrorObserver is replaced. public class Case { private static final String autopsyVer = Version.getVersion(); // current version of autopsy. Change it when the version is changed From 88f40b55b7fd3111ac0129bfb7a8a6000b3a7123 Mon Sep 17 00:00:00 2001 From: Karl Mortensen Date: Thu, 4 Jun 2015 11:39:15 -0400 Subject: [PATCH 8/9] not public --- .../sleuthkit/autopsy/casemodule/IntervalErrorReportData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/IntervalErrorReportData.java b/Core/src/org/sleuthkit/autopsy/casemodule/IntervalErrorReportData.java index 9d9603b8e9..2900bdacf3 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/IntervalErrorReportData.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/IntervalErrorReportData.java @@ -29,7 +29,7 @@ import org.sleuthkit.datamodel.SleuthkitCase; * notifications. When the time between notifications has expired, the next * error encountered will cause a report to be shown to the user. */ -public class IntervalErrorReportData implements SleuthkitCase.ErrorObserver { +class IntervalErrorReportData implements SleuthkitCase.ErrorObserver { private static volatile IntervalErrorReportData instance; private long newProblems; From 91be468c74870f46c1f30253bbddce80cb83955b Mon Sep 17 00:00:00 2001 From: Karl Mortensen Date: Thu, 4 Jun 2015 11:43:13 -0400 Subject: [PATCH 9/9] private addproblems --- Core/src/org/sleuthkit/autopsy/casemodule/Case.java | 11 ----------- .../autopsy/casemodule/IntervalErrorReportData.java | 2 +- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 78c4f20c50..11ac5611b3 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -218,13 +218,6 @@ public class Case { this.services = new Services(db); } - /** - * Does initialization that would leak a reference to this if done in the - * constructor. - */ - private void init() { - } - /** * Gets the currently opened case, if there is one. * @@ -375,8 +368,6 @@ public class Case { * constructor. */ Case newCase = new Case(caseName, caseNumber, examiner, configFilePath, xmlcm, db, caseType); - newCase.init(); - changeCase(newCase); } @@ -435,8 +426,6 @@ public class Case { * constructor. */ Case openedCase = new Case(caseName, caseNumber, examiner, configFilePath, xmlcm, db, caseType); - openedCase.init(); - changeCase(openedCase); } catch (Exception ex) { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/IntervalErrorReportData.java b/Core/src/org/sleuthkit/autopsy/casemodule/IntervalErrorReportData.java index 2900bdacf3..679917c476 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/IntervalErrorReportData.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/IntervalErrorReportData.java @@ -79,7 +79,7 @@ class IntervalErrorReportData implements SleuthkitCase.ErrorObserver { * @param newProblems the newProblems to set * @param ex the exception for this error */ - public void addProblems(long newProblems, Exception ex) { + private void addProblems(long newProblems, Exception ex) { this.newProblems += newProblems; this.totalProblems += newProblems;