Fix assorted Case action bugs

This commit is contained in:
Richard Cordovano 2017-05-02 15:22:32 -04:00
parent a4d2196484
commit ee43f71137
25 changed files with 1253 additions and 1210 deletions

View File

@ -96,10 +96,10 @@ Case.databaseConnectionInfo.error.msg=Error accessing database server connection
Case.open.msgDlg.updated.msg=Updated case database schema.\nA backup copy of the database with the following path has been made\:\n {0} Case.open.msgDlg.updated.msg=Updated case database schema.\nA backup copy of the database with the following path has been made\:\n {0}
Case.open.msgDlg.updated.title=Case Database Schema Update Case.open.msgDlg.updated.title=Case Database Schema Update
Case.open.exception.multiUserCaseNotEnabled=Cannot open a multi-user case if multi-user cases are not enabled. See Tools, Options, Multi-user. Case.open.exception.multiUserCaseNotEnabled=Cannot open a multi-user case if multi-user cases are not enabled. See Tools, Options, Multi-user.
Case.checkImgExist.confDlg.doesntExist.msg={0} has detected that one of the images associated with \n\ Case.checkImgExist.confDlg.doesntExist.msg=One of the images associated with \n\
this case are missing. Would you like to search for them now?\n\ this case are missing. Would you like to search for them now?\n\
Previously, the image was located at\:\n\ Previously, the image was located at\:\n\
{1}\n\ {0}\n\
Please note that you will still be able to browse directories and generate reports\n\ Please note that you will still be able to browse directories and generate reports\n\
if you choose No, but you will not be able to view file content or run the ingest process. if you choose No, but you will not be able to view file content or run the ingest process.
Case.checkImgExist.confDlg.doesntExist.title=Missing Image Case.checkImgExist.confDlg.doesntExist.title=Missing Image
@ -136,12 +136,6 @@ IntervalErrorReport.NewIssues=new issue(s)
IntervalErrorReport.TotalIssues=total issue(s) IntervalErrorReport.TotalIssues=total issue(s)
IntervalErrorReport.ErrorText=Database Connection Error IntervalErrorReport.ErrorText=Database Connection Error
CasePropertiesAction.window.title=Case Properties CasePropertiesAction.window.title=Case Properties
CasePropertiesForm.updateCaseName.msgDlg.empty.msg=The caseName cannot be empty.
CasePropertiesForm.updateCaseName.msgDlg.empty.title=Error
CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.msg=The Case Name cannot contain any of this following symbol\: \\ / \: * ? " < > |
CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.title=Error
CasePropertiesForm.updateCaseName.confMsg.msg=Are you sure you want to update the case name from "{0}" to "{1}"?
CasePropertiesForm.updateCaseName.confMsg.title=Change Case Name
CueBannerPanel.title.text=Open Recent Case CueBannerPanel.title.text=Open Recent Case
GeneralFilter.rawImageDesc.text=Raw Images (*.img, *.dd, *.001, *.aa, *.raw, *.bin) GeneralFilter.rawImageDesc.text=Raw Images (*.img, *.dd, *.001, *.aa, *.raw, *.bin)
GeneralFilter.encaseImageDesc.text=Encase Images (*.e01) GeneralFilter.encaseImageDesc.text=Encase Images (*.e01)

View File

@ -73,10 +73,6 @@ Case.getCurCase.exception.noneOpen=\u4f5c\u696d\u4e2d\u306e\u30b1\u30fc\u30b9\u3
Case.open.msgDlg.updated.msg=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30b9\u30ad\u30fc\u30de\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\u3002\n\u6b21\u306e\u30d1\u30b9\u3092\u6301\u3064\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u30b3\u30d4\u30fc\u304c\u4f5c\u6210\u3055\u308c\u307e\u3057\u305f\uff1a\n\ Case.open.msgDlg.updated.msg=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30b9\u30ad\u30fc\u30de\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\u3002\n\u6b21\u306e\u30d1\u30b9\u3092\u6301\u3064\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u30b3\u30d4\u30fc\u304c\u4f5c\u6210\u3055\u308c\u307e\u3057\u305f\uff1a\n\
{0} {0}
Case.open.msgDlg.updated.title=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30b9\u30ad\u30fc\u30de\u3092\u66f4\u65b0 Case.open.msgDlg.updated.title=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30b9\u30ad\u30fc\u30de\u3092\u66f4\u65b0
Case.checkImgExist.confDlg.doesntExist.msg={0} \u304c\u3053\u306e\u30b1\u30fc\u30b9\u306b\u95a2\u9023\u3059\u308b\u30a4\u30e1\u30fc\u30b8\u306e\u3046\u3061\uff11\u3064\u304c\u6b20\u843d\u3057\u3066\u3044\u308b\u306e\u3092\u691c\u51fa\u3057\u307e\u3057\u305f\u3002\u305d\u308c\u3092\u4eca\u304b\u3089\u691c\u7d22\u3057\u307e\u3059\u304b\uff1f\n\n\
\u4ee5\u524d\u3001\u30a4\u30e1\u30fc\u30b8\u306f\u6b21\u306b\u3042\u308a\u307e\u3057\u305f\uff1a\n\
{1}\n\
\u3044\u3044\u3048\u3092\u9078\u629e\u3057\u3066\u3082\u3001\u4eca\u5f8c\u3082\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u95b2\u89a7\u3057\u3001\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u304c\u3067\u304d\u307e\u3059\u304c\u3001\n\u30d5\u30a1\u30a4\u30eb\u30b3\u30f3\u30c6\u30f3\u30c4\u306e\u8868\u793a\u307e\u305f\u306f\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30d7\u30ed\u30bb\u30b9\u306e\u5b9f\u884c\u304c\u3067\u304d\u306a\u304f\u306a\u308a\u307e\u3059\u3002
Case.checkImgExist.confDlg.doesntExist.title=\u6b20\u843d\u3057\u3066\u3044\u308b\u30a4\u30e1\u30fc\u30b8 Case.checkImgExist.confDlg.doesntExist.title=\u6b20\u843d\u3057\u3066\u3044\u308b\u30a4\u30e1\u30fc\u30b8
Case.addImg.exception.msg=\u30b1\u30fc\u30b9\u306b\u30a4\u30e1\u30fc\u30b8\u3092\u8ffd\u52a0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f Case.addImg.exception.msg=\u30b1\u30fc\u30b9\u306b\u30a4\u30e1\u30fc\u30b8\u3092\u8ffd\u52a0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f
Case.updateCaseName.exception.msg=\u30b1\u30fc\u30b9\u540d\u3092\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 Case.updateCaseName.exception.msg=\u30b1\u30fc\u30b9\u540d\u3092\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002
@ -99,10 +95,6 @@ CaseDeleteAction.msgDlg.caseDelete.msg=\u30b1\u30fc\u30b9\u304c\u524a\u9664\u305
CaseOpenAction.autFilter.title={0} \u30b1\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb ( {1}) CaseOpenAction.autFilter.title={0} \u30b1\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb ( {1})
CaseOpenAction.msgDlg.cantOpenCase.title=\u30b1\u30fc\u30b9\u3092\u958b\u304f\u969b\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f CaseOpenAction.msgDlg.cantOpenCase.title=\u30b1\u30fc\u30b9\u3092\u958b\u304f\u969b\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f
CasePropertiesAction.window.title=\u30b1\u30fc\u30b9\u30d7\u30ed\u30d1\u30c6\u30a3 CasePropertiesAction.window.title=\u30b1\u30fc\u30b9\u30d7\u30ed\u30d1\u30c6\u30a3
CasePropertiesForm.updateCaseName.msgDlg.empty.msg=\u30b1\u30fc\u30b9\u540d\u306f\u7a7a\u767d\u3067\u306f\u3044\u3051\u307e\u305b\u3093\u3002
CasePropertiesForm.updateCaseName.msgDlg.empty.title=\u30a8\u30e9\u30fc
CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.msg=\u30b1\u30fc\u30b9\u540d\u306b\u306f\u6b21\u306e\u8a18\u53f7\u3092\u542b\u3081\u307e\u305b\u3093\uff1a\\ / \: * ? " < > |
CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.title=\u30a8\u30e9\u30fc
CueBannerPanel.title.text=\u6700\u8fd1\u958b\u3044\u305f\u30b1\u30fc\u30b9\u3092\u958b\u304f CueBannerPanel.title.text=\u6700\u8fd1\u958b\u3044\u305f\u30b1\u30fc\u30b9\u3092\u958b\u304f
GeneralFilter.rawImageDesc.text=\u30ed\u30fc\u30a4\u30e1\u30fc\u30b8(*.img, *.dd, *.001, *.aa, *.raw, *.bin) GeneralFilter.rawImageDesc.text=\u30ed\u30fc\u30a4\u30e1\u30fc\u30b8(*.img, *.dd, *.001, *.aa, *.raw, *.bin)
GeneralFilter.encaseImageDesc.text=\u30a8\u30f3\u30b1\u30fc\u30b9\u30a4\u30e1\u30fc\u30b8(*.e01) GeneralFilter.encaseImageDesc.text=\u30a8\u30f3\u30b1\u30fc\u30b9\u30a4\u30e1\u30fc\u30b8(*.e01)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,49 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.casemodule;
/**
* Exception thrown when a case action (e.g., create, open, close, delete) is
* cancelled before it is completed.
*/
class CaseActionCancelledException extends CaseActionException {
private static final long serialVersionUID = 1L;
/**
* Constructs an exception thrown when a case action (e.g., create, open,
* close, delete) is cancelled before it is completed.
*
* @param message An error message.
*/
CaseActionCancelledException(String message) {
super(message);
}
/**
* Constructs an exception thrown when a case action (e.g., create, open,
* close, delete) is cancelled before it is completed.
*
* @param message An error message.
* @param cause An excception that caused this exception to be thrown.
*/
CaseActionCancelledException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2012 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -19,15 +19,30 @@
package org.sleuthkit.autopsy.casemodule; package org.sleuthkit.autopsy.casemodule;
/** /**
* Exception thrown when case action (such as open, close, create) resulted in * Exception thrown when a case action (e.g., create, open, close, delete)
* an error * experiences an error condition.
*/ */
public class CaseActionException extends Exception { public class CaseActionException extends Exception {
private static final long serialVersionUID = 1L;
/**
* Constructs an exception thrown when a case action (e.g., create, open,
* close, delete) experiences an error condition.
*
* @param message An error message.
*/
public CaseActionException(String message) { public CaseActionException(String message) {
super(message); super(message);
} }
/**
* Constructs an exception thrown when a case action (e.g., create, open,
* close, delete) experiences an error condition.
*
* @param message An error message.
* @param cause An excception that caused this exception to be thrown.
*/
public CaseActionException(String message, Throwable cause) { public CaseActionException(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -19,10 +19,6 @@
package org.sleuthkit.autopsy.casemodule; package org.sleuthkit.autopsy.casemodule;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeEvent;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
@ -32,44 +28,40 @@ import org.openide.util.NbBundle.Messages;
*/ */
class CaseInformationPanel extends javax.swing.JPanel { class CaseInformationPanel extends javax.swing.JPanel {
private static final Logger logger = Logger.getLogger(CaseInformationPanel.class.getName()); private static final long serialVersionUID = 1L;
/** /**
* Creates new form CaseInformationPanel * Constructs a panel for displaying the case information, including both
* case details and ingest job history.
*/ */
CaseInformationPanel() { CaseInformationPanel() {
initComponents(); initComponents();
customizeComponents(); customizeComponents();
} }
@Messages({"CaseInformationPanel.caseDetails.header=Case Details", @Messages({
"CaseInformationPanel.ingestJobInfo.header=Ingest History", "CaseInformationPanel.caseDetails.header=Case Details",
"CaseInformationPanel.loadMetadataFail.message=Failed to load case metadata.", "CaseInformationPanel.ingestJobInfo.header=Ingest History"
"CaseInformationPanel.loadMetadataFail.title=Metadata load failure",}) })
private void customizeComponents() { private void customizeComponents() {
try { CasePropertiesPanel propertiesPanel = new CasePropertiesPanel(Case.getCurrentCase());
Case currentCase = Case.getCurrentCase(); propertiesPanel.setSize(propertiesPanel.getPreferredSize());
String crDate = currentCase.getCreatedDate(); this.tabbedPane.addTab(Bundle.CaseInformationPanel_caseDetails_header(), propertiesPanel);
String caseDir = currentCase.getCaseDirectory();
// put the image paths information into hashmap
Map<Long, String> imgPaths = Case.getImagePaths(currentCase.getSleuthkitCase());
CasePropertiesPanel cpf = new CasePropertiesPanel(currentCase, crDate, caseDir, imgPaths);
cpf.setSize(cpf.getPreferredSize());
this.tabbedPane.addTab(Bundle.CaseInformationPanel_caseDetails_header(), cpf);
this.tabbedPane.addTab(Bundle.CaseInformationPanel_ingestJobInfo_header(), new IngestJobInfoPanel()); this.tabbedPane.addTab(Bundle.CaseInformationPanel_ingestJobInfo_header(), new IngestJobInfoPanel());
this.tabbedPane.addChangeListener((ChangeEvent e) -> { this.tabbedPane.addChangeListener((ChangeEvent e) -> {
tabbedPane.getSelectedComponent().setSize(tabbedPane.getSelectedComponent().getPreferredSize()); tabbedPane.getSelectedComponent().setSize(tabbedPane.getSelectedComponent().getPreferredSize());
}); });
} catch (CaseMetadata.CaseMetadataException ex) {
logger.log(Level.SEVERE, "Failed to load case metadata.", ex);
JOptionPane.showMessageDialog(null, Bundle.IngestJobInfoPanel_loadIngestJob_error_text(), Bundle.IngestJobInfoPanel_loadIngestJob_error_title(), JOptionPane.ERROR_MESSAGE);
}
} }
/**
* Adds an action listener to the Close button of the panel.
*
* @param action
*/
void addCloseButtonAction(ActionListener action) { void addCloseButtonAction(ActionListener action) {
this.closeButton.addActionListener(action); this.closeButton.addActionListener(action);
} }
/** /**
* This method is called from within the constructor to initialize the form. * 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 * WARNING: Do NOT modify this code. The content of this method is always
@ -127,7 +119,7 @@ class CaseInformationPanel extends javax.swing.JPanel {
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
// TODO add your handling code here: // Used by CasePropertiesAction
}//GEN-LAST:event_closeButtonActionPerformed }//GEN-LAST:event_closeButtonActionPerformed

View File

@ -54,7 +54,9 @@ public final class CaseMetadata {
private static final String FILE_EXTENSION = ".aut"; private static final String FILE_EXTENSION = ".aut";
private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss (z)"); private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss (z)");
//fields from schema version 1 /*
* Fields from schema version 1
*/
private static final String SCHEMA_VERSION_ONE = "1.0"; private static final String SCHEMA_VERSION_ONE = "1.0";
private final static String ROOT_ELEMENT_NAME = "AutopsyCase"; //NON-NLS private final static String ROOT_ELEMENT_NAME = "AutopsyCase"; //NON-NLS
private final static String SCHEMA_VERSION_ELEMENT_NAME = "SchemaVersion"; //NON-NLS private final static String SCHEMA_VERSION_ELEMENT_NAME = "SchemaVersion"; //NON-NLS
@ -68,22 +70,28 @@ public final class CaseMetadata {
private final static String CASE_DATABASE_NAME_ELEMENT_NAME = "DatabaseName"; //NON-NLS private final static String CASE_DATABASE_NAME_ELEMENT_NAME = "DatabaseName"; //NON-NLS
private final static String TEXT_INDEX_NAME_ELEMENT = "TextIndexName"; //NON-NLS private final static String TEXT_INDEX_NAME_ELEMENT = "TextIndexName"; //NON-NLS
//fields from schema version 2 /*
* Fields from schema version 2
*/
private static final String SCHEMA_VERSION_TWO = "2.0"; private static final String SCHEMA_VERSION_TWO = "2.0";
private final static String AUTOPSY_CREATED_BY_ELEMENT_NAME = "CreatedByAutopsyVersion"; //NON-NLS private final static String AUTOPSY_CREATED_BY_ELEMENT_NAME = "CreatedByAutopsyVersion"; //NON-NLS
private final static String CASE_DATABASE_ABSOLUTE_PATH_ELEMENT_NAME = "Database"; //NON-NLS private final static String CASE_DB_ABSOLUTE_PATH_ELEMENT_NAME = "Database"; //NON-NLS
private final static String TEXT_INDEX_ELEMENT = "TextIndex"; //NON-NLS private final static String TEXT_INDEX_ELEMENT = "TextIndex"; //NON-NLS
//fields from schema version 3 /*
* Fields from schema version 3
*/
private static final String SCHEMA_VERSION_THREE = "3.0"; private static final String SCHEMA_VERSION_THREE = "3.0";
private final static String CASE_DISPLAY_NAME_ELEMENT_NAME = "DisplayName"; //NON-NLS private final static String CASE_DISPLAY_NAME_ELEMENT_NAME = "DisplayName"; //NON-NLS
private final static String CASE_DATABASE_NAME_RELATIVE_ELEMENT_NAME = "CaseDatabase"; //NON-NLS private final static String CASE_DB_NAME_RELATIVE_ELEMENT_NAME = "CaseDatabase"; //NON-NLS
//unread fields, these are regenerated on save /*
* Unread fields, regenerated on save.
*/
private final static String MODIFIED_DATE_ELEMENT_NAME = "ModifiedDate"; //NON-NLS private final static String MODIFIED_DATE_ELEMENT_NAME = "ModifiedDate"; //NON-NLS
private final static String AUTOPSY_SAVED_BY_ELEMENT_NAME = "SavedByAutopsyVersion"; //NON-NLS private final static String AUTOPSY_SAVED_BY_ELEMENT_NAME = "SavedByAutopsyVersion"; //NON-NLS
private static final String CURRENT_SCHEMA_VERSION = SCHEMA_VERSION_THREE; private final static String CURRENT_SCHEMA_VERSION = SCHEMA_VERSION_THREE;
private final Path metadataFilePath; private final Path metadataFilePath;
private Case.CaseType caseType; private Case.CaseType caseType;
@ -92,8 +100,8 @@ public final class CaseMetadata {
private String caseNumber; private String caseNumber;
private String examiner; private String examiner;
private String caseDatabaseName; private String caseDatabaseName;
private String caseDatabasePath; private String caseDatabasePath; // Legacy
private String textIndexName; private String textIndexName; // Legacy
private String createdDate; private String createdDate;
private String createdByVersion; private String createdByVersion;
@ -107,8 +115,9 @@ public final class CaseMetadata {
} }
/** /**
* Constructs an object that provides access to the case metadata stored in * Constructs a CaseMetadata object for a new case. The metadata is not
* a new case metadata file that is created using the supplied metadata. * persisted to the case metadata file until writeFile or a setX method is
* called.
* *
* @param caseDirectory The case directory. * @param caseDirectory The case directory.
* @param caseType The type of case. * @param caseType The type of case.
@ -117,29 +126,24 @@ public final class CaseMetadata {
* user. * user.
* @param caseNumber The case number. * @param caseNumber The case number.
* @param examiner The name of the case examiner. * @param examiner The name of the case examiner.
* @param caseDatabase For a single-user case, the full path to the case
* database file. For a multi-user case, the case
* database name.
*
* @throws CaseMetadataException If the new case metadata file cannot be
* created.
*/ */
CaseMetadata(String caseDirectory, Case.CaseType caseType, String caseName, String caseDisplayName, String caseNumber, String examiner, String caseDatabase) throws CaseMetadataException { CaseMetadata(String caseDirectory, Case.CaseType caseType, String caseName, String caseDisplayName, String caseNumber, String examiner) {
metadataFilePath = Paths.get(caseDirectory, caseDisplayName + FILE_EXTENSION); metadataFilePath = Paths.get(caseDirectory, caseDisplayName + FILE_EXTENSION);
this.caseType = caseType; this.caseType = caseType;
this.caseName = caseName; this.caseName = caseName;
this.caseDisplayName = caseDisplayName; this.caseDisplayName = caseDisplayName;
this.caseNumber = caseNumber; this.caseNumber = caseNumber;
this.examiner = examiner; this.examiner = examiner;
this.caseDatabaseName = caseDatabase; caseDatabaseName = "";
caseDatabasePath = "";
textIndexName = "";
createdByVersion = Version.getVersion(); createdByVersion = Version.getVersion();
createdDate = CaseMetadata.DATE_FORMAT.format(new Date()); createdDate = CaseMetadata.DATE_FORMAT.format(new Date());
writeToFile();
} }
/** /**
* Constructs an object that provides access to the case metadata stored in * Constructs a CaseMetadata object for an existing case. The metadata is
* an existing case metadata file. * read from an existing case metadata file.
* *
* @param metadataFilePath The full path to the case metadata file. * @param metadataFilePath The full path to the case metadata file.
* *
@ -179,7 +183,7 @@ public final class CaseMetadata {
} }
/** /**
* Gets the immutable case name, set at case creation. * Gets the unique and immutable case name.
* *
* @return The case display name. * @return The case display name.
*/ */
@ -193,22 +197,23 @@ public final class CaseMetadata {
* @return The case display name. * @return The case display name.
*/ */
public String getCaseDisplayName() { public String getCaseDisplayName() {
return this.caseDisplayName; return caseDisplayName;
} }
/** /**
* Sets the case display name. This does not change the name of the case * Sets the case display name.
* directory, the case database, or the text index name.
* *
* @param caseName A case display name. * @param caseDisplayName A case display name.
*
* @throws CaseMetadataException If the operation fails.
*/ */
void setCaseDisplayName(String caseName) throws CaseMetadataException { void setCaseDisplayName(String caseDisplayName) throws CaseMetadataException {
String oldCaseName = caseName; String oldCaseDisplayName = this.caseDisplayName;
this.caseDisplayName = caseName; this.caseDisplayName = caseDisplayName;
try { try {
writeToFile(); writeToFile();
} catch (CaseMetadataException ex) { } catch (CaseMetadataException ex) {
this.caseDisplayName = oldCaseName; this.caseDisplayName = oldCaseDisplayName;
throw ex; throw ex;
} }
} }
@ -234,32 +239,35 @@ public final class CaseMetadata {
/** /**
* Gets the name of the case database. * Gets the name of the case database.
* *
* @return The case database name. * @return The case database name, may be empty.
*/ */
public String getCaseDatabaseName() { public String getCaseDatabaseName() {
return caseDatabaseName; return caseDatabaseName;
} }
/** /**
* Sets the text index name. * Sets the name of the case database.
* *
* @param caseTextIndexName The text index name. * @param caseDatabaseName The case database name.
*
* @throws CaseMetadataException If the operation fails.
*/ */
void setTextIndexName(String caseTextIndexName) throws CaseMetadataException { void setCaseDatabaseName(String caseDatabaseName) throws CaseMetadataException {
String oldIndexName = caseTextIndexName; String oldCaseDatabaseName = this.caseDatabaseName;
this.textIndexName = caseTextIndexName; this.caseDatabaseName = caseDatabaseName;
try { try {
writeToFile(); writeToFile();
} catch (CaseMetadataException ex) { } catch (CaseMetadataException ex) {
this.textIndexName = oldIndexName; this.caseDatabaseName = oldCaseDatabaseName;
throw ex; throw ex;
} }
} }
/** /**
* Gets the text index name. * Gets the text index name. This is a legacy field and will be empty for
* cases created with Autopsy 4.4.0 and above.
* *
* @return The name of the text index for the case. * @return The name of the text index for the case, may be empty.
*/ */
public String getTextIndexName() { public String getTextIndexName() {
return textIndexName; return textIndexName;
@ -268,7 +276,7 @@ public final class CaseMetadata {
/** /**
* Gets the date the case was created. * Gets the date the case was created.
* *
* @return The date this case was created as a string * @return The date this case was created, as a string.
*/ */
String getCreatedDate() { String getCreatedDate() {
return createdDate; return createdDate;
@ -278,7 +286,9 @@ public final class CaseMetadata {
* Sets the date the case was created. Used for preserving the case creation * Sets the date the case was created. Used for preserving the case creation
* date during single-user to multi-user case conversion. * date during single-user to multi-user case conversion.
* *
* @param createdDate The date the case was created as a string. * @param createdDate The date the case was created, as a string.
*
* @throws CaseMetadataException If the operation fails.
*/ */
void setCreatedDate(String createdDate) throws CaseMetadataException { void setCreatedDate(String createdDate) throws CaseMetadataException {
String oldCreatedDate = createdDate; String oldCreatedDate = createdDate;
@ -304,13 +314,15 @@ public final class CaseMetadata {
* Sets the Autopsy version that created the case. Used for preserving this * Sets the Autopsy version that created the case. Used for preserving this
* metadata during single-user to multi-user case conversion. * metadata during single-user to multi-user case conversion.
* *
* @param buildVersion An build version identifier. * @param buildVersion A build version identifier.
*
* @throws CaseMetadataException If the operation fails.
*/ */
void setCreatedByVersion(String buildVersion) throws CaseMetadataException { void setCreatedByVersion(String buildVersion) throws CaseMetadataException {
String oldCreatedByVersion = this.createdByVersion; String oldCreatedByVersion = this.createdByVersion;
this.createdByVersion = buildVersion; this.createdByVersion = buildVersion;
try { try {
this.writeToFile(); writeToFile();
} catch (CaseMetadataException ex) { } catch (CaseMetadataException ex) {
this.createdByVersion = oldCreatedByVersion; this.createdByVersion = oldCreatedByVersion;
throw ex; throw ex;
@ -381,8 +393,8 @@ public final class CaseMetadata {
createChildElement(doc, caseElement, CASE_NUMBER_ELEMENT_NAME, caseNumber); createChildElement(doc, caseElement, CASE_NUMBER_ELEMENT_NAME, caseNumber);
createChildElement(doc, caseElement, EXAMINER_ELEMENT_NAME, examiner); createChildElement(doc, caseElement, EXAMINER_ELEMENT_NAME, examiner);
createChildElement(doc, caseElement, CASE_TYPE_ELEMENT_NAME, caseType.toString()); createChildElement(doc, caseElement, CASE_TYPE_ELEMENT_NAME, caseType.toString());
createChildElement(doc, caseElement, CASE_DATABASE_ABSOLUTE_PATH_ELEMENT_NAME, caseDatabasePath); createChildElement(doc, caseElement, CASE_DB_ABSOLUTE_PATH_ELEMENT_NAME, caseDatabasePath);
createChildElement(doc, caseElement, CASE_DATABASE_NAME_RELATIVE_ELEMENT_NAME, caseDatabaseName); createChildElement(doc, caseElement, CASE_DB_NAME_RELATIVE_ELEMENT_NAME, caseDatabaseName);
createChildElement(doc, caseElement, TEXT_INDEX_ELEMENT, textIndexName); createChildElement(doc, caseElement, TEXT_INDEX_ELEMENT, textIndexName);
} }
@ -451,15 +463,19 @@ public final class CaseMetadata {
if (null == this.caseType) { if (null == this.caseType) {
throw new CaseMetadataException("Case metadata file corrupted"); throw new CaseMetadataException("Case metadata file corrupted");
} }
if (schemaVersion.equals(SCHEMA_VERSION_ONE)) { switch (schemaVersion) {
case SCHEMA_VERSION_ONE:
this.caseDatabaseName = getElementTextContent(caseElement, CASE_DATABASE_NAME_ELEMENT_NAME, true); this.caseDatabaseName = getElementTextContent(caseElement, CASE_DATABASE_NAME_ELEMENT_NAME, true);
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_NAME_ELEMENT, true); this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_NAME_ELEMENT, true);
} else if (schemaVersion.equals(SCHEMA_VERSION_TWO)) { break;
this.caseDatabaseName = getElementTextContent(caseElement, CASE_DATABASE_ABSOLUTE_PATH_ELEMENT_NAME, true); case SCHEMA_VERSION_TWO:
this.caseDatabaseName = getElementTextContent(caseElement, CASE_DB_ABSOLUTE_PATH_ELEMENT_NAME, true);
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, false); this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, false);
} else { break;
this.caseDatabaseName = getElementTextContent(caseElement, CASE_DATABASE_NAME_RELATIVE_ELEMENT_NAME, true); default:
this.caseDatabaseName = getElementTextContent(caseElement, CASE_DB_NAME_RELATIVE_ELEMENT_NAME, true);
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, false); this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, false);
break;
} }
/* /*
@ -489,7 +505,7 @@ public final class CaseMetadata {
* @param elementName The element name. * @param elementName The element name.
* @param contentIsRequired Whether or not the content is required. * @param contentIsRequired Whether or not the content is required.
* *
* @return The text content, may be empty if not required. * @return The text content, may be empty If not required.
* *
* @throws CaseMetadataException If the element is missing or content is * @throws CaseMetadataException If the element is missing or content is
* required and it is empty. * required and it is empty.
@ -530,7 +546,7 @@ public final class CaseMetadata {
* @return The full path to the case database file for a single-user case. * @return The full path to the case database file for a single-user case.
* *
* @throws UnsupportedOperationException If called for a multi-user case. * @throws UnsupportedOperationException If called for a multi-user case.
* @deprecated * @deprecated Do not use.
*/ */
@Deprecated @Deprecated
public String getCaseDatabasePath() throws UnsupportedOperationException { public String getCaseDatabasePath() throws UnsupportedOperationException {

View File

@ -125,6 +125,7 @@ public final class CaseOpenAction extends CallableSystemAction implements Action
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
StartupWindowProvider.getInstance().open(); StartupWindowProvider.getInstance().open();
} catch (ExecutionException ex) { } catch (ExecutionException ex) {
if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) {
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", path), ex); //NON-NLS logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", path), ex); //NON-NLS
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
JOptionPane.showMessageDialog( JOptionPane.showMessageDialog(
@ -132,6 +133,7 @@ public final class CaseOpenAction extends CallableSystemAction implements Action
ex.getCause().getMessage(), //get the message of the wrapped exception ex.getCause().getMessage(), //get the message of the wrapped exception
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
}
StartupWindowProvider.getInstance().open(); StartupWindowProvider.getInstance().open();
} }
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));

View File

@ -22,7 +22,6 @@ import java.awt.Dimension;
import java.awt.Toolkit; import java.awt.Toolkit;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.Action; import javax.swing.Action;
import javax.swing.JDialog; import javax.swing.JDialog;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
@ -43,11 +42,11 @@ final class CasePropertiesAction extends CallableSystemAction {
CasePropertiesAction() { CasePropertiesAction() {
putValue(Action.NAME, NbBundle.getMessage(CasePropertiesAction.class, "CTL_CasePropertiesAction")); putValue(Action.NAME, NbBundle.getMessage(CasePropertiesAction.class, "CTL_CasePropertiesAction"));
this.setEnabled(false); this.setEnabled(false);
Case.addEventSubscriber(Case.Events.CURRENT_CASE.toString(), new PropertyChangeListener() { Case.addEventSubscriber(Case.Events.CURRENT_CASE.toString(), (PropertyChangeEvent evt) -> {
@Override if (null == evt.getNewValue()) {
public void propertyChange(PropertyChangeEvent evt) { casePropertiesDialog = null;
setEnabled(null != evt.getNewValue());
} }
setEnabled(null != evt.getNewValue());
}); });
} }

View File

@ -16,63 +16,57 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.casemodule; package org.sleuthkit.autopsy.casemodule;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction; import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
/** /**
* A panel that allows the user to view various properties of the current case * A panel that allows the user to view various properties of a case and change
* and change the display name of the case. * the display name of the case.
*/ */
class CasePropertiesPanel extends javax.swing.JPanel { class CasePropertiesPanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private Case current = null; private static final Logger LOGGER = Logger.getLogger(CasePropertiesPanel.class.getName());
private static JPanel caller; // panel for error private final Case theCase;
CasePropertiesPanel(Case currentCase, String crDate, String caseDir, Map<Long, String> imgPaths) throws CaseMetadata.CaseMetadataException { /**
* Constructs a panel that allows the user to view various properties of the
* current case and change the display name of the case.
*
* @param aCase A case.
*/
CasePropertiesPanel(Case aCase) {
initComponents(); initComponents();
caseNameTextField.setText(currentCase.getDisplayName()); theCase = aCase;
String caseNumber = currentCase.getNumber(); caseNameTextField.setText(theCase.getDisplayName());
String caseNumber = theCase.getNumber();
if (!caseNumber.isEmpty()) { if (!caseNumber.isEmpty()) {
caseNumberField.setText(caseNumber); caseNumberField.setText(caseNumber);
} else { } else {
caseNumberField.setText("N/A"); caseNumberField.setText("N/A");
} }
String examiner = currentCase.getExaminer(); String examiner = theCase.getExaminer();
if (!examiner.isEmpty()) { if (!examiner.isEmpty()) {
examinerField.setText(examiner); examinerField.setText(examiner);
} else { } else {
examinerField.setText("N/A"); examinerField.setText("N/A");
} }
crDateField.setText(crDate); crDateField.setText(theCase.getCreatedDate());
caseDirField.setText(caseDir); caseDirField.setText(theCase.getCaseDirectory());
current = currentCase; if (Case.CaseType.SINGLE_USER_CASE == theCase.getCaseType()) {
dbNameField.setText(Paths.get(theCase.getCaseDirectory(), theCase.getMetadata().getCaseDatabaseName()).toString());
CaseMetadata caseMetadata = currentCase.getCaseMetadata();
if (caseMetadata.getCaseType() == Case.CaseType.SINGLE_USER_CASE) {
dbNameField.setText(Paths.get(caseMetadata.getCaseDirectory(), caseMetadata.getCaseDatabaseName()).toString());
} else { } else {
dbNameField.setText(caseMetadata.getCaseDatabaseName()); dbNameField.setText(theCase.getMetadata().getCaseDatabaseName());
} }
Case.CaseType caseType = caseMetadata.getCaseType(); Case.CaseType caseType = theCase.getCaseType();
caseTypeField.setText(caseType.getLocalizedDisplayName()); caseTypeField.setText(caseType.getLocalizedDisplayName());
if (caseType == Case.CaseType.SINGLE_USER_CASE) { deleteCaseButton.setEnabled(Case.CaseType.SINGLE_USER_CASE == caseType);
deleteCaseButton.setEnabled(true);
} else {
deleteCaseButton.setEnabled(false);
}
} }
/** /**
@ -259,59 +253,35 @@ class CasePropertiesPanel extends javax.swing.JPanel {
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
/** /**
* Updates the case name. * Updates the case display name.
* *
* @param evt The action event * @param evt The action event
*/ */
@NbBundle.Messages({
"CasePropertiesPanel.errorDialog.emptyCaseNameMessage=No case name entered.",
"CasePropertiesPanel.errorDialog.invalidCaseNameMessage=Case names cannot include the following symbols: \\, /, :, *, ?, \", <, >, |"
})
private void updateCaseNameButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_updateCaseNameButtonActionPerformed private void updateCaseNameButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_updateCaseNameButtonActionPerformed
String oldCaseName = Case.getCurrentCase().getDisplayName(); String newCaseDisplayName = caseNameTextField.getText();
String newCaseName = caseNameTextField.getText(); if (newCaseDisplayName.equals(theCase.getDisplayName())) {
// check if the old and new case name is not equal return;
if (!oldCaseName.equals(newCaseName)) { }
// check if the case name is empty if (newCaseDisplayName.trim().isEmpty()) {
if (newCaseName.trim().isEmpty()) { MessageNotifyUtil.Message.error(Bundle.CasePropertiesPanel_errorDialog_emptyCaseNameMessage());
JOptionPane.showMessageDialog(caller, return;
NbBundle.getMessage(this.getClass(), }
"CasePropertiesForm.updateCaseName.msgDlg.empty.msg"),
NbBundle.getMessage(this.getClass(), if (!Case.isValidName(newCaseDisplayName)) {
"CasePropertiesForm.updateCaseName.msgDlg.empty.title"), MessageNotifyUtil.Message.error(Bundle.CasePropertiesPanel_errorDialog_invalidCaseNameMessage());
JOptionPane.ERROR_MESSAGE); return;
} else // check if case Name contain one of this following symbol: }
// \ / : * ? " < > |
{
if (newCaseName.contains("\\") || newCaseName.contains("/") || newCaseName.contains(":")
|| newCaseName.contains("*") || newCaseName.contains("?") || newCaseName.contains("\"")
|| newCaseName.contains("<") || newCaseName.contains(">") || newCaseName.contains("|")) {
String errorMsg = NbBundle
.getMessage(this.getClass(), "CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.msg");
JOptionPane.showMessageDialog(caller, errorMsg,
NbBundle.getMessage(this.getClass(),
"CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.title"),
JOptionPane.ERROR_MESSAGE);
} else {
// ask for the confirmation first
String confMsg = NbBundle
.getMessage(this.getClass(), "CasePropertiesForm.updateCaseName.confMsg.msg", oldCaseName,
newCaseName);
NotifyDescriptor d = new NotifyDescriptor.Confirmation(confMsg,
NbBundle.getMessage(this.getClass(),
"CasePropertiesForm.updateCaseName.confMsg.title"),
NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
d.setValue(NotifyDescriptor.NO_OPTION);
Object res = DialogDisplayer.getDefault().notify(d);
if (res != null && res == DialogDescriptor.YES_OPTION) {
// if user select "Yes"
String oldPath = current.getCaseMetadata().getFilePath().toString();
try { try {
current.updateCaseName(oldCaseName, oldPath, newCaseName, oldPath); theCase.updateDisplayName(newCaseDisplayName);
} catch (CaseActionException ex) { } catch (CaseActionException ex) {
Logger.getLogger(CasePropertiesPanel.class.getName()).log(Level.WARNING, "Error: problem updating case name.", ex); //NON-NLS MessageNotifyUtil.Message.error(ex.getLocalizedMessage());
} LOGGER.log(Level.SEVERE, "Failed to update case display name", ex); //NON-NLS
}
}
}
} }
}//GEN-LAST:event_updateCaseNameButtonActionPerformed }//GEN-LAST:event_updateCaseNameButtonActionPerformed

View File

@ -94,15 +94,17 @@ final class NewCaseWizardAction extends CallableSystemAction {
AddImageAction addImageAction = SystemAction.get(AddImageAction.class); AddImageAction addImageAction = SystemAction.get(AddImageAction.class);
addImageAction.actionPerformed(null); addImageAction.actionPerformed(null);
} catch (InterruptedException | ExecutionException ex) { } catch (InterruptedException | ExecutionException ex) {
if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) {
logger.log(Level.SEVERE, String.format("Error creating case %s", wizardDescriptor.getProperty("caseName")), ex); //NON-NLS logger.log(Level.SEVERE, String.format("Error creating case %s", wizardDescriptor.getProperty("caseName")), ex); //NON-NLS
JOptionPane.showMessageDialog( JOptionPane.showMessageDialog(
WindowManager.getDefault().getMainWindow(), WindowManager.getDefault().getMainWindow(),
(ex instanceof ExecutionException ? ex.getCause().getMessage() : ex.getMessage()), (ex instanceof ExecutionException ? ex.getCause().getMessage() : ex.getMessage()),
NbBundle.getMessage(this.getClass(), "CaseCreateAction.msgDlg.cantCreateCase.msg"), //NON-NLS NbBundle.getMessage(this.getClass(), "CaseCreateAction.msgDlg.cantCreateCase.msg"), //NON-NLS
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
}
doFailedCaseCleanup(wizardDescriptor);
StartupWindowProvider.getInstance().close(); StartupWindowProvider.getInstance().close();
StartupWindowProvider.getInstance().open(); StartupWindowProvider.getInstance().open();
doFailedCaseCleanup(wizardDescriptor);
} finally { } finally {
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
} }

View File

@ -38,29 +38,21 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.ModuleSettings;
/** /**
* The "New Case" wizard panel with a component on it. This class represents * The first panel of the New Case wizard.
* data of wizard step. It defers creation and initialization of UI component of
* wizard panel into getComponent() method.
*/ */
class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDescriptor> { class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDescriptor> {
/**
* The visual component that displays this panel. If you need to access the
* component from this class, just use getComponent().
*/
private NewCaseVisualPanel1 component;
private Boolean isFinish = false;
private static String createdDirectory;
private static final String PROP_BASECASE = "LBL_BaseCase_PATH"; //NON-NLS
private static final Logger logger = Logger.getLogger(NewCaseWizardPanel1.class.getName()); private static final Logger logger = Logger.getLogger(NewCaseWizardPanel1.class.getName());
private static final String PROP_BASECASE = "LBL_BaseCase_PATH"; //NON-NLS
private static String createdDirectory;
private final Set<ChangeListener> listeners = new HashSet<>(1);
private NewCaseVisualPanel1 component;
private boolean isFinish;
/** /**
* Get the visual component for the panel. In this template, the component * Get the visual component for the panel.
* is kept separate. This can be more efficient: if the wizard is created
* but never displayed, or not all panels are displayed, it is better to
* create only those which really need to be visible.
* *
* @return component the UI component of this wizard panel * @return The UI component of this wizard panel
*/ */
@Override @Override
public NewCaseVisualPanel1 getComponent() { public NewCaseVisualPanel1 getComponent() {
@ -71,65 +63,57 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
} }
/** /**
* Help for this panel. When the panel is active, this is used as the help * Gets the help object for this panel. When the panel is active, this is
* for the wizard dialog. * used as the help for the wizard dialog.
* *
* @return HelpCtx.DEFAULT_HELP the help for this panel * @return The help for this panel.
*/ */
@Override @Override
public HelpCtx getHelp() { public HelpCtx getHelp() {
// Show no Help button for this panel: /*
* Currently, no help is provided for this panel.
*/
return HelpCtx.DEFAULT_HELP; return HelpCtx.DEFAULT_HELP;
// If you have context help:
// return new HelpCtx(SampleWizardPanel1.class);
} }
/** /**
* Tests whether the panel is finished. If the panel is valid, the "Finish" * Tests whether the panel is finished. If the panel is valid, the "Finish"
* button will be enabled. * button will be enabled.
* *
* @return boolean true if all the fields are correctly filled, false * @return boolean True if all the fields are correctly filled, false
* otherwise * otherwise.
*/ */
@Override @Override
public boolean isValid() { public boolean isValid() {
// If it is always OK to press Next or Finish, then:
return isFinish; return isFinish;
// If it depends on some condition (form filled out...), then:
// return someCondition();
// and when this condition changes (last form field filled in...) then:
// fireChangeEvent();
// and uncomment the complicated stuff below.
} }
private final Set<ChangeListener> listeners = new HashSet<>(1); // or can use ChangeSupport in NB 6.0
/** /**
* Adds a listener to changes of the panel's validity. * Adds a change listener to this panel.
* *
* @param l the change listener to add * @param listener The change listener to add.
*/ */
@Override @Override
public final void addChangeListener(ChangeListener l) { public final void addChangeListener(ChangeListener listener) {
synchronized (listeners) { synchronized (listeners) {
listeners.add(l); listeners.add(listener);
} }
} }
/** /**
* Removes a listener to changes of the panel's validity. * Removes a change listener from this panel.
* *
* @param l the change listener to move * @param listener The change listener to remove.
*/ */
@Override @Override
public final void removeChangeListener(ChangeListener l) { public final void removeChangeListener(ChangeListener listener) {
synchronized (listeners) { synchronized (listeners) {
listeners.remove(l); listeners.remove(listener);
} }
} }
/** /**
* This method is auto-generated. It seems that this method is used to * Notifies any registerd change listeners of a change in the panel.
* listen to any change in this wizard panel.
*/ */
protected final void fireChangeEvent() { protected final void fireChangeEvent() {
Iterator<ChangeListener> it; Iterator<ChangeListener> it;
@ -153,12 +137,8 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
fireChangeEvent(); fireChangeEvent();
} }
// You can use a settings object to keep track of state. Normally the
// settings object will be the WizardDescriptor, so you can use
// WizardDescriptor.getProperty & putProperty to store information entered
// by the user.
/** /**
* Provides the wizard panel with the current data--either the default data * Provides the wizard panel with the current data - either the default data
* or already-modified settings, if the user used the previous and/or next * or already-modified settings, if the user used the previous and/or next
* buttons. This method can be called multiple times on one instance of * buttons. This method can be called multiple times on one instance of
* WizardDescriptor.Panel. * WizardDescriptor.Panel.
@ -322,4 +302,5 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
} }
} }
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2015 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -28,35 +28,19 @@ import org.openide.WizardValidationException;
import org.openide.util.HelpCtx; import org.openide.util.HelpCtx;
import org.openide.windows.WindowManager; import org.openide.windows.WindowManager;
import java.awt.Cursor; import java.awt.Cursor;
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
/** /**
* The "New Case" wizard panel with a component on it. This class represents * The second panel of the New Case wizard.
* data of wizard step. It defers creation and initialization of UI component of
* wizard panel into getComponent() method.
*
* @author jantonius
*/ */
class NewCaseWizardPanel2 implements WizardDescriptor.ValidatingPanel<WizardDescriptor> { class NewCaseWizardPanel2 implements WizardDescriptor.ValidatingPanel<WizardDescriptor> {
/**
* The visual component that displays this panel. If you need to access the
* component from this class, just use getComponent().
*/
private NewCaseVisualPanel2 component; private NewCaseVisualPanel2 component;
private Boolean isFinish = true; private final Set<ChangeListener> listeners = new HashSet<>(1);
private String caseName;
private String caseDir;
private String createdDirectory;
private CaseType caseType;
/** /**
* Get the visual component for the panel. In this template, the component * Get the visual component for the panel.
* is kept separate. This can be more efficient: if the wizard is created
* but never displayed, or not all panels are displayed, it is better to
* create only those which really need to be visible.
* *
* @return component the UI component of this wizard panel * @return component The UI component of this wizard panel.
*/ */
@Override @Override
public NewCaseVisualPanel2 getComponent() { public NewCaseVisualPanel2 getComponent() {
@ -67,17 +51,17 @@ class NewCaseWizardPanel2 implements WizardDescriptor.ValidatingPanel<WizardDesc
} }
/** /**
* Help for this panel. When the panel is active, this is used as the help * Gets the help object for this panel. When the panel is active, this is
* for the wizard dialog. * used as the help for the wizard dialog.
* *
* @return HelpCtx.DEFAULT_HELP the help for this panel * @return The help for this panel.
*/ */
@Override @Override
public HelpCtx getHelp() { public HelpCtx getHelp() {
// Show no Help button for this panel: /*
* Currently, no help is provided for this panel.
*/
return HelpCtx.DEFAULT_HELP; return HelpCtx.DEFAULT_HELP;
// If you have context help:
// return new HelpCtx(SampleWizardPanel1.class);
} }
/** /**
@ -89,43 +73,35 @@ class NewCaseWizardPanel2 implements WizardDescriptor.ValidatingPanel<WizardDesc
*/ */
@Override @Override
public boolean isValid() { public boolean isValid() {
// If it is always OK to press Next or Finish, then: return true;
return isFinish;
// If it depends on some condition (form filled out...), then:
// return someCondition();
// and when this condition changes (last form field filled in...) then:
// fireChangeEvent();
// and uncomment the complicated stuff below.
} }
private final Set<ChangeListener> listeners = new HashSet<ChangeListener>(1); // or can use ChangeSupport in NB 6.0
/** /**
* Adds a listener to changes of the panel's validity. * Adds a change listener to this panel.
* *
* @param l the change listener to add * @param listener The change listener to add.
*/ */
@Override @Override
public final void addChangeListener(ChangeListener l) { public final void addChangeListener(ChangeListener listener) {
synchronized (listeners) { synchronized (listeners) {
listeners.add(l); listeners.add(listener);
} }
} }
/** /**
* Removes a listener to changes of the panel's validity. * Removes a change listener from this panel.
* *
* @param l the change listener to move * @param listener The change listener to remove.
*/ */
@Override @Override
public final void removeChangeListener(ChangeListener l) { public final void removeChangeListener(ChangeListener listener) {
synchronized (listeners) { synchronized (listeners) {
listeners.remove(l); listeners.remove(listener);
} }
} }
/** /**
* This method is auto-generated. It seems that this method is used to * Notifies any registerd change listeners of a change in the panel.
* listen to any change in this wizard panel.
*/ */
protected final void fireChangeEvent() { protected final void fireChangeEvent() {
Iterator<ChangeListener> it; Iterator<ChangeListener> it;
@ -138,10 +114,6 @@ class NewCaseWizardPanel2 implements WizardDescriptor.ValidatingPanel<WizardDesc
} }
} }
// You can use a settings object to keep track of state. Normally the
// settings object will be the WizardDescriptor, so you can use
// WizardDescriptor.getProperty & putProperty to store information entered
// by the user.
/** /**
* Provides the wizard panel with the current data--either the default data * Provides the wizard panel with the current data--either the default data
* or already-modified settings, if the user used the previous and/or next * or already-modified settings, if the user used the previous and/or next
@ -152,10 +124,6 @@ class NewCaseWizardPanel2 implements WizardDescriptor.ValidatingPanel<WizardDesc
*/ */
@Override @Override
public void readSettings(WizardDescriptor settings) { public void readSettings(WizardDescriptor settings) {
caseName = (String) settings.getProperty("caseName"); //NON-NLS
caseDir = (String) settings.getProperty("caseParentDir"); //NON-NLS
createdDirectory = (String) settings.getProperty("createdDirectory"); //NON-NLS
caseType = CaseType.values()[(int) settings.getProperty("caseType")]; //NON-NLS
} }
/** /**

View File

@ -125,13 +125,15 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
try { try {
Case.openAsCurrentCase(casePath); Case.openAsCurrentCase(casePath);
} catch (CaseActionException ex) { } catch (CaseActionException ex) {
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", casePath), ex); //NON-NLS
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) {
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", casePath), ex); //NON-NLS
JOptionPane.showMessageDialog( JOptionPane.showMessageDialog(
WindowManager.getDefault().getMainWindow(), WindowManager.getDefault().getMainWindow(),
ex.getMessage(), // Should be user-friendly ex.getMessage(), // Should be user-friendly
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
}
StartupWindowProvider.getInstance().open(); StartupWindowProvider.getInstance().open();
}); });
} }

View File

@ -407,9 +407,11 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
String[] casePaths = new String[LENGTH]; String[] casePaths = new String[LENGTH];
String currentCasePath = null; String currentCasePath = null;
try { try {
currentCasePath = Case.getCurrentCase().getCaseMetadata().getFilePath().toString(); currentCasePath = Case.getCurrentCase().getMetadata().getFilePath().toString();
} catch (IllegalStateException ex) { } catch (IllegalStateException ex) {
// in case there is no current case. /*
* There may be no current case.
*/
} }
Iterator<RecentCase> mostRecentFirst = recentCases.descendingIterator(); Iterator<RecentCase> mostRecentFirst = recentCases.descendingIterator();

View File

@ -65,17 +65,20 @@ class RecentItems implements ActionListener {
try { try {
Case.openAsCurrentCase(caseMetaDataFilePath); Case.openAsCurrentCase(caseMetaDataFilePath);
} catch (CaseActionException ex) { } catch (CaseActionException ex) {
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetaDataFilePath), ex); //NON-NLS
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
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
JOptionPane.showMessageDialog( JOptionPane.showMessageDialog(
WindowManager.getDefault().getMainWindow(), WindowManager.getDefault().getMainWindow(),
ex.getMessage(), ex.getMessage(),
NbBundle.getMessage(RecentItems.this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS NbBundle.getMessage(RecentItems.this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
}
StartupWindowProvider.getInstance().open(); StartupWindowProvider.getInstance().open();
}); });
} }
}).start(); }).
start();
} }
} }
} }

View File

@ -204,8 +204,8 @@ public class SingleUserCaseConverter {
icd.getNewCaseName(), icd.getNewCaseName(),
icd.getNewCaseName(), icd.getNewCaseName(),
oldCaseMetadata.getCaseNumber(), oldCaseMetadata.getCaseNumber(),
oldCaseMetadata.getExaminer(), oldCaseMetadata.getExaminer());
dbName); newCaseMetadata.setCaseDatabaseName(dbName);
// Set created date. This calls writefile, no need to call it again // Set created date. This calls writefile, no need to call it again
newCaseMetadata.setCreatedDate(oldCaseMetadata.getCreatedDate()); newCaseMetadata.setCreatedDate(oldCaseMetadata.getCreatedDate());
newCaseMetadata.setCreatedByVersion(oldCaseMetadata.getCreatedByVersion()); newCaseMetadata.setCreatedByVersion(oldCaseMetadata.getCreatedByVersion());

View File

@ -59,7 +59,7 @@ public final class LoggingProgressIndicator implements ProgressIndicator {
@Override @Override
public void progress(int workUnitsCompleted) { public void progress(int workUnitsCompleted) {
LOGGER.log(Level.INFO, "{1} of {2} total work units completed", new Object[]{workUnitsCompleted, this.totalWorkUnits}); LOGGER.log(Level.INFO, "{0} of {1} total work units completed", new Object[]{workUnitsCompleted, this.totalWorkUnits});
} }
@Override @Override
@ -68,8 +68,8 @@ public final class LoggingProgressIndicator implements ProgressIndicator {
} }
@Override @Override
public void finish(String message) { public void finish() {
LOGGER.log(Level.INFO, "{0} finished", message); LOGGER.log(Level.INFO, "Finished");
} }
} }

View File

@ -21,6 +21,8 @@ package org.sleuthkit.autopsy.framework;
import java.awt.Dialog; import java.awt.Dialog;
import java.awt.Frame; import java.awt.Frame;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;
import javax.swing.JDialog; import javax.swing.JDialog;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import org.openide.DialogDescriptor; import org.openide.DialogDescriptor;
@ -30,14 +32,17 @@ import org.openide.util.HelpCtx;
/** /**
* A progress indicator that displays progress using a modal dialog with a * A progress indicator that displays progress using a modal dialog with a
* message label, a progress bar, and optionally, a configurable set of buttons * message label, a progress bar, and optionally, a configurable set of buttons
* with a button listener. * with a button listener. Setting a cancelling flag which locks in a cancelling
* message and an indeterminate progress bar is supported.
*/ */
@ThreadSafe
public final class ModalDialogProgressIndicator implements ProgressIndicator { public final class ModalDialogProgressIndicator implements ProgressIndicator {
private final Frame parent; private final Frame parent;
private final ProgressPanel progressPanel; private final ProgressPanel progressPanel;
private final Dialog dialog; private final Dialog dialog;
private final ActionListener buttonListener; @GuardedBy("this")
private boolean cancelling;
/** /**
* Creates a progress indicator that displays progress using a modal dialog * Creates a progress indicator that displays progress using a modal dialog
@ -54,6 +59,7 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
public ModalDialogProgressIndicator(Frame parent, String title, Object[] buttonLabels, Object focusedButtonLabel, ActionListener buttonListener) { public ModalDialogProgressIndicator(Frame parent, String title, Object[] buttonLabels, Object focusedButtonLabel, ActionListener buttonListener) {
this.parent = parent; this.parent = parent;
progressPanel = new ProgressPanel(); progressPanel = new ProgressPanel();
progressPanel.setIndeterminate(true);
DialogDescriptor dialogDescriptor = new DialogDescriptor( DialogDescriptor dialogDescriptor = new DialogDescriptor(
progressPanel, progressPanel,
title, title,
@ -64,7 +70,6 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
HelpCtx.DEFAULT_HELP, HelpCtx.DEFAULT_HELP,
buttonListener); buttonListener);
dialog = DialogDisplayer.getDefault().createDialog(dialogDescriptor); dialog = DialogDisplayer.getDefault().createDialog(dialogDescriptor);
this.buttonListener = buttonListener;
} }
/** /**
@ -77,31 +82,10 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
public ModalDialogProgressIndicator(Frame parent, String title) { public ModalDialogProgressIndicator(Frame parent, String title) {
this.parent = parent; this.parent = parent;
progressPanel = new ProgressPanel(); progressPanel = new ProgressPanel();
progressPanel.setIndeterminate(true);
dialog = new JDialog(parent, title, true); dialog = new JDialog(parent, title, true);
dialog.add(progressPanel); dialog.add(progressPanel);
dialog.pack(); dialog.pack();
buttonListener = null;
}
/**
* Calls setVisible on the underlying modal dialog.
*
* @param isVisible True or false.
*/
public void setVisible(boolean isVisible) {
if (isVisible) {
dialog.setLocationRelativeTo(parent);
}
this.dialog.setVisible(isVisible);
}
/**
* Gets the button listener for the dialog, if there is one.
*
* @return The button listener or null.
*/
public ActionListener getButtonListener() {
return buttonListener;
} }
/** /**
@ -112,14 +96,14 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
* @param totalWorkUnits The total number of work units. * @param totalWorkUnits The total number of work units.
*/ */
@Override @Override
public void start(String message, int totalWorkUnits) { public synchronized void start(String message, int totalWorkUnits) {
SwingUtilities.invokeLater(new Runnable() { cancelling = false;
@Override SwingUtilities.invokeLater(() -> {
public void run() { progressPanel.setIndeterminate(false);
progressPanel.setInderminate(false);
progressPanel.setMessage(message); progressPanel.setMessage(message);
progressPanel.setMaximum(totalWorkUnits); progressPanel.setMaximum(totalWorkUnits);
} dialog.setLocationRelativeTo(parent);
this.dialog.setVisible(true);
}); });
} }
@ -130,13 +114,28 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
* @param message The initial progress message. * @param message The initial progress message.
*/ */
@Override @Override
public void start(String message) { public synchronized void start(String message) {
SwingUtilities.invokeLater(new Runnable() { cancelling = false;
@Override SwingUtilities.invokeLater(() -> {
public void run() { progressPanel.setIndeterminate(true);
progressPanel.setInderminate(true);
progressPanel.setMessage(message); progressPanel.setMessage(message);
dialog.setLocationRelativeTo(parent);
this.dialog.setVisible(true);
});
} }
/**
* Sets a cancelling message and makes the progress bar indeterminate. Once
* cancel has been called, the progress indicator no longer accepts updates
* unless start is called again.
*
* @param cancellingMessage
*/
public synchronized void setCancelling(String cancellingMessage) {
cancelling = true;
SwingUtilities.invokeLater(() -> {
progressPanel.setIndeterminate(false);
progressPanel.setMessage(cancellingMessage);
}); });
} }
@ -147,15 +146,14 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
* @param message The initial progress message. * @param message The initial progress message.
*/ */
@Override @Override
public void switchToIndeterminate(String message) { public synchronized void switchToIndeterminate(String message) {
SwingUtilities.invokeLater(new Runnable() { if (!cancelling) {
@Override SwingUtilities.invokeLater(() -> {
public void run() { progressPanel.setIndeterminate(true);
progressPanel.setInderminate(true);
progressPanel.setMessage(message); progressPanel.setMessage(message);
}
}); });
} }
}
/** /**
* Switches the progress indicator to determinate mode (the total number of * Switches the progress indicator to determinate mode (the total number of
@ -166,17 +164,16 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
* @param totalWorkUnits The total number of work units to be completed. * @param totalWorkUnits The total number of work units to be completed.
*/ */
@Override @Override
public void switchToDeterminate(String message, int workUnitsCompleted, int totalWorkUnits) { public synchronized void switchToDeterminate(String message, int workUnitsCompleted, int totalWorkUnits) {
SwingUtilities.invokeLater(new Runnable() { if (!cancelling) {
@Override SwingUtilities.invokeLater(() -> {
public void run() { progressPanel.setIndeterminate(false);
progressPanel.setInderminate(false);
progressPanel.setMessage(message); progressPanel.setMessage(message);
progressPanel.setMaximum(totalWorkUnits); progressPanel.setMaximum(totalWorkUnits);
progressPanel.setCurrent(workUnitsCompleted); progressPanel.setCurrent(workUnitsCompleted);
}
}); });
} }
}
/** /**
* Updates the progress indicator with a progress message. * Updates the progress indicator with a progress message.
@ -184,14 +181,13 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
* @param message The progress message. * @param message The progress message.
*/ */
@Override @Override
public void progress(String message) { public synchronized void progress(String message) {
SwingUtilities.invokeLater(new Runnable() { if (!cancelling) {
@Override SwingUtilities.invokeLater(() -> {
public void run() {
progressPanel.setMessage(message); progressPanel.setMessage(message);
}
}); });
} }
}
/** /**
* Updates the progress indicator with the number of work units completed so * Updates the progress indicator with the number of work units completed so
@ -201,14 +197,13 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
* @param workUnitsCompleted Number of work units completed so far. * @param workUnitsCompleted Number of work units completed so far.
*/ */
@Override @Override
public void progress(int workUnitsCompleted) { public synchronized void progress(int workUnitsCompleted) {
SwingUtilities.invokeLater(new Runnable() { if (!cancelling) {
@Override SwingUtilities.invokeLater(() -> {
public void run() {
progressPanel.setCurrent(workUnitsCompleted); progressPanel.setCurrent(workUnitsCompleted);
}
}); });
} }
}
/** /**
* Updates the progress indicator with a progress message and the number of * Updates the progress indicator with a progress message and the number of
@ -219,28 +214,22 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
* @param workUnitsCompleted Number of work units completed so far. * @param workUnitsCompleted Number of work units completed so far.
*/ */
@Override @Override
public void progress(String message, int workUnitsCompleted) { public synchronized void progress(String message, int workUnitsCompleted) {
SwingUtilities.invokeLater(new Runnable() { if (!cancelling) {
@Override SwingUtilities.invokeLater(() -> {
public void run() {
progressPanel.setMessage(message); progressPanel.setMessage(message);
progressPanel.setCurrent(workUnitsCompleted); progressPanel.setCurrent(workUnitsCompleted);
}
}); });
} }
}
/** /**
* Finishes the progress indicator when the task is completed. * Finishes the progress indicator when the task is completed.
*
* @param message The finished message.
*/ */
@Override @Override
public void finish(String message) { public synchronized void finish() {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(() -> {
@Override this.dialog.setVisible(false);
public void run() {
progressPanel.setMessage(message);
}
}); });
} }

View File

@ -46,6 +46,7 @@ public interface ProgressIndicator {
/** /**
* Switches the progress indicator to indeterminate mode (the total number * Switches the progress indicator to indeterminate mode (the total number
* of work units to be completed is unknown). * of work units to be completed is unknown).
*
* @param message The initial progress message. * @param message The initial progress message.
*/ */
public void switchToIndeterminate(String message); public void switchToIndeterminate(String message);
@ -88,9 +89,7 @@ public interface ProgressIndicator {
/** /**
* Finishes the progress indicator when the task is completed. * Finishes the progress indicator when the task is completed.
*
* @param message The finished message.
*/ */
void finish(String message); void finish();
} }

View File

@ -35,7 +35,7 @@ class ProgressPanel extends javax.swing.JPanel {
this.progressMessage.setText(message); this.progressMessage.setText(message);
} }
void setInderminate(boolean indeterminate) { void setIndeterminate(boolean indeterminate) {
this.progressBar.setIndeterminate(indeterminate); this.progressBar.setIndeterminate(indeterminate);
} }

View File

@ -54,7 +54,7 @@ public class SilentProgressIndicator implements ProgressIndicator {
} }
@Override @Override
public void finish(String message) { public void finish() {
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -25,19 +25,15 @@ import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor; import org.openide.NotifyDescriptor;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProvider;
import org.openide.util.lookup.ServiceProviders;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.framework.AutopsyService; import org.sleuthkit.autopsy.framework.AutopsyService;
@ServiceProviders(value = {@ServiceProvider(service = AutopsyService.class)})
/** /**
* Creates and handles closing of ImageWriter objects. * Creates and handles closing of ImageWriter objects. Currently, ImageWriter is
* Currently, ImageWriter is only enabled for local disks, and local disks can * only enabled for local disks, and local disks can not be processed in multi
* not be processed in multi user mode. If ImageWriter is ever enabled for multi user * user mode. If ImageWriter is ever enabled for multi user cases this code will
* cases this code will need to be revised. * need to be revised.
*/ */
@ServiceProvider(service = AutopsyService.class)
public class ImageWriterService implements AutopsyService { public class ImageWriterService implements AutopsyService {
private static final List<ImageWriter> imageWriters = new ArrayList<>(); // Contains all Image Writer objects private static final List<ImageWriter> imageWriters = new ArrayList<>(); // Contains all Image Writer objects
@ -45,6 +41,7 @@ public class ImageWriterService implements AutopsyService {
/** /**
* Create an image writer object for the given data source ID. * Create an image writer object for the given data source ID.
*
* @param imageId ID for the image * @param imageId ID for the image
*/ */
public static void createImageWriter(Long imageId, ImageWriterSettings settings) { public static void createImageWriter(Long imageId, ImageWriterSettings settings) {
@ -66,9 +63,13 @@ public class ImageWriterService implements AutopsyService {
@Override @Override
public void closeCaseResources(CaseContext context) throws AutopsyServiceException { public void closeCaseResources(CaseContext context) throws AutopsyServiceException {
synchronized (imageWritersLock) {
if (imageWriters.isEmpty()) {
return;
}
context.getProgressIndicator().progress(NbBundle.getMessage(this.getClass(), "ImageWriterService.waitingForVHDs")); context.getProgressIndicator().progress(NbBundle.getMessage(this.getClass(), "ImageWriterService.waitingForVHDs"));
synchronized(imageWritersLock){
// If any of our ImageWriter objects haven't started the finish task, set the cancel flag // If any of our ImageWriter objects haven't started the finish task, set the cancel flag
// to make sure they don't start now. The reason they haven't started is that // to make sure they don't start now. The reason they haven't started is that
// ingest was not complete, and the user already confirmed that they want to exit // ingest was not complete, and the user already confirmed that they want to exit

View File

@ -53,7 +53,7 @@ public class TestAutopsyService implements AutopsyService {
progressIndicator.progress(80); progressIndicator.progress(80);
Thread.sleep(1000L); Thread.sleep(1000L);
progressIndicator.progress(100); progressIndicator.progress(100);
progressIndicator.finish("First task completed by Test Autopsy Service."); progressIndicator.finish();
progressIndicator.start("Test Autopsy Service doing second task..."); progressIndicator.start("Test Autopsy Service doing second task...");
for (int i = 0; i < 10000; ++i) { for (int i = 0; i < 10000; ++i) {
logger.log(Level.INFO, "Test Autopsy Service simulating work on second task"); logger.log(Level.INFO, "Test Autopsy Service simulating work on second task");
@ -62,7 +62,7 @@ public class TestAutopsyService implements AutopsyService {
break; break;
} }
} }
progressIndicator.finish("Second task completed by Test Autopsy Service."); progressIndicator.finish();
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
logger.log(Level.INFO, "Test Autopsy Service interrupted (cancelled) while doing first task, cancel requested = {0}", context.cancelRequested()); logger.log(Level.INFO, "Test Autopsy Service interrupted (cancelled) while doing first task, cancel requested = {0}", context.cancelRequested());
} }

View File

@ -200,6 +200,10 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService {
"SolrSearch.openCore.msg=Opening text index", "SolrSearch.openCore.msg=Opening text index",
"SolrSearch.complete.msg=Text index successfully opened"}) "SolrSearch.complete.msg=Text index successfully opened"})
public void openCaseResources(CaseContext context) throws AutopsyServiceException { public void openCaseResources(CaseContext context) throws AutopsyServiceException {
if (context.cancelRequested()) {
return;
}
ProgressIndicator progress = context.getProgressIndicator(); ProgressIndicator progress = context.getProgressIndicator();
int totalNumProgressUnits = 7; int totalNumProgressUnits = 7;
int progressUnitsCompleted = 0; int progressUnitsCompleted = 0;