diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 1becc449d5..c6284859f1 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -125,7 +125,6 @@ public class Case { private static final String LOG_FOLDER = "Log"; //NON-NLS private static final String REPORTS_FOLDER = "Reports"; //NON-NLS private static final String TEMP_FOLDER = "Temp"; //NON-NLS - private static final int MIN_SECS_BETWEEN_TSK_ERROR_REPORTS = 60; private static final String MODULE_FOLDER = "ModuleOutput"; //NON-NLS private static final long EXECUTOR_AWAIT_TIMEOUT_SECS = 5; private static final String CASE_ACTION_THREAD_NAME = "%s-case-action"; diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/actions/EamCaseEditDetailsDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/actions/EamCaseEditDetailsDialog.java index 6bbdeac316..c00f0583d8 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/actions/EamCaseEditDetailsDialog.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/actions/EamCaseEditDetailsDialog.java @@ -43,7 +43,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization; import org.sleuthkit.autopsy.centralrepository.optionspanel.AddNewOrganizationDialog; /** - * Handle editing details of cases within the Central Repository + * Handle editing details of cases within the central repository */ public class EamCaseEditDetailsDialog extends JDialog { @@ -531,14 +531,14 @@ public class EamCaseEditDetailsDialog extends JDialog { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); if (!EamDb.isEnabled()) { - LOGGER.log(Level.SEVERE, "Central Repository database not enabled"); // NON-NLS + LOGGER.log(Level.SEVERE, "Central repository database not enabled"); // NON-NLS return; } try { dbManager.updateCase(eamCase); } catch (IllegalArgumentException | EamDbException ex) { - LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database", ex); // NON-NLS + LOGGER.log(Level.SEVERE, "Error connecting to central repository database", ex); // NON-NLS } finally { setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java index 4c804cf703..8ab241fa3b 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java @@ -66,8 +66,8 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; * View correlation results from other cases */ @ServiceProvider(service = DataContentViewer.class, position = 8) -@Messages({"DataContentViewerOtherCases.title=Other Data Sources", - "DataContentViewerOtherCases.toolTip=Displays instances of the selected file/artifact from other data sources.",}) +@Messages({"DataContentViewerOtherCases.title=Other Occurrences", + "DataContentViewerOtherCases.toolTip=Displays instances of the selected file/artifact from other occurrences.",}) public class DataContentViewerOtherCases extends javax.swing.JPanel implements DataContentViewer { private final static Logger LOGGER = Logger.getLogger(DataContentViewerOtherCases.class.getName()); @@ -370,7 +370,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D * * @param node The node to view * - * @return A collection of Central Repository artifacts to display + * @return A collection of central repository artifacts to display */ private Collection getArtifactsFromCorrelatableAttributes(Node node) { Collection ret = new ArrayList<>(); @@ -450,7 +450,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D /** * Query the db for artifact instances from other cases correlated to the - * given Central Repository artifact. + * given central repository artifact. * * @param eamArtifact The artifact to correlate against * @@ -474,12 +474,12 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D } /** - * Get the Global File Instances matching the given eamArtifact and convert - * them to Central Repository Artifact Instancess. + * Get the global file instances matching the given eamArtifact and convert + * them to central repository artifact instancess. * * @param eamArtifact Artifact to use for ArtifactTypeEnum matching * - * @return List of Central Repository Artifact Instances, empty list if none + * @return List of central repository artifact instances, empty list if none * found */ public Collection getReferenceInstancesAsArtifactInstances(EamArtifact eamArtifact) { @@ -530,8 +530,8 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D * * @param node The node being viewed. */ - @Messages({"DataContentViewerOtherCases.table.isempty=There are no associated artifacts or files from other cases to display.", - "DataContentViewerOtherCases.table.noArtifacts=Correlation cannot be performed on the selected file; likely missing MD5 hash."}) + @Messages({"DataContentViewerOtherCases.table.isempty=There are no associated artifacts or files from other occurrences to display.", + "DataContentViewerOtherCases.table.noArtifacts=Correlation cannot be performed on the selected file."}) private void populateTable(Node node) { String dataSourceName = getDataSourceNameFromNode(node); String deviceId = getDeviceIdFromNode(node); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java index 266211493b..ba2358d75c 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java @@ -175,9 +175,9 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel { } /** - * Add one local Central Repository Artifact to the table. + * Add one local central repository artifact to the table. * - * @param eamArtifact Central Repository Artifact to add to the + * @param eamArtifact central repository artifact to add to the * table */ public void addEamArtifact(EamArtifact eamArtifact) { diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifact.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifact.java index 3c2db37e39..7c7a7b0afb 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifact.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifact.java @@ -170,7 +170,7 @@ public class EamArtifact implements Serializable { * * @param id Unique ID for this Correlation Type * @param displayName Name of this type displayed in the UI. - * @param dbTableName Central Repository db table where data of this type is stored. + * @param dbTableName Central repository db table where data of this type is stored. * Must start with a lowercase letter and only contain * lowercase letters, numbers, and '_' characters. * @param supported Is this Type currently supported @@ -190,10 +190,10 @@ public class EamArtifact implements Serializable { /** * Constructior for custom types where we do not know the Type ID until * the row has been entered into the correlation_types table - * in the Central Repository. + * in the central repository. * * @param displayName Name of this type displayed in the UI. - * @param dbTableName Central Repository db table where data of this type is stored + * @param dbTableName Central repository db table where data of this type is stored * Must start with a lowercase letter and only contain * lowercase letters, numbers, and '_' characters. * @param supported Is this Type currently supported diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java index cdf4d3d360..c7aa222fd6 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java @@ -190,7 +190,8 @@ public class IngestEventsListener { } } - @NbBundle.Messages({"IngestEventsListener.prevcases.text=Previous Cases", + @NbBundle.Messages({"IngestEventsListener.prevTaggedSet.text=Previously Tagged As Notable (Central Repository)", + "IngestEventsListener.prevCaseComment.text=Previous Case: ", "IngestEventsListener.ingestmodule.name=Correlation Engine"}) private void postCorrelatedBadArtifactToBlackboard(BlackboardArtifact bbArtifact, List caseDisplayNames) { @@ -200,9 +201,9 @@ public class IngestEventsListener { String MODULE_NAME = Bundle.IngestEventsListener_ingestmodule_name(); BlackboardArtifact tifArtifact = af.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT); BlackboardAttribute att = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, - Bundle.IngestEventsListener_prevcases_text()); + Bundle.IngestEventsListener_prevTaggedSet_text()); BlackboardAttribute att2 = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, MODULE_NAME, - "Previous Case: " + caseDisplayNames.stream().distinct().collect(Collectors.joining(",", "", ""))); + Bundle.IngestEventsListener_prevCaseComment_text() + caseDisplayNames.stream().distinct().collect(Collectors.joining(",", "", ""))); tifArtifact.addAttribute(att); tifArtifact.addAttribute(att2); tifArtifact.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, MODULE_NAME, bbArtifact.getArtifactID())); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java index 1c0a66d646..bfd23e38c2 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java @@ -54,7 +54,8 @@ import org.sleuthkit.datamodel.TskDataException; * Ingest module for inserting entries into the Central Repository database on * ingest of a data source */ -@Messages({"IngestModule.prevcases.text=Previous Cases"}) +@Messages({"IngestModule.prevTaggedSet.text=Previously Tagged As Notable (Central Repository)", + "IngestModule.prevCaseComment.text=Previous Case: "}) class IngestModule implements FileIngestModule { private final static Logger LOGGER = Logger.getLogger(IngestModule.class.getName()); @@ -187,7 +188,7 @@ class IngestModule implements FileIngestModule { // see ArtifactManagerTimeTester for details @Messages({ "IngestModule.notfyBubble.title=Central Repository Not Initialized", - "IngestModule.errorMessage.isNotEnabled=Central Repository settings are not initialized, cannot run Correlation Engine ingest module." + "IngestModule.errorMessage.isNotEnabled=Central repository settings are not initialized, cannot run Correlation Engine ingest module." }) @Override public void startUp(IngestJobContext context) throws IngestModuleException { @@ -210,8 +211,8 @@ class IngestModule implements FileIngestModule { // Don't allow sqlite central repo databases to be used for multi user cases if((Case.getCurrentCase().getCaseType() == Case.CaseType.MULTI_USER_CASE) && (EamDbPlatformEnum.getSelectedPlatform() == EamDbPlatformEnum.SQLITE)){ - LOGGER.log(Level.SEVERE, "Cannot run correlation engine on a multi-user case with a SQLite Central Repository."); - throw new IngestModuleException("Cannot run on a multi-user case with a SQLite Central Repository."); // NON-NLS + LOGGER.log(Level.SEVERE, "Cannot run correlation engine on a multi-user case with a SQLite central repository."); + throw new IngestModuleException("Cannot run on a multi-user case with a SQLite central repository."); // NON-NLS } jobId = context.getJobId(); eamCase = new EamCase(Case.getCurrentCase().getName(), Case.getCurrentCase().getDisplayName()); @@ -230,8 +231,8 @@ class IngestModule implements FileIngestModule { try { dbManager = EamDb.getInstance(); } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database.", ex); // NON-NLS - throw new IngestModuleException("Error connecting to Central Repository database.", ex); // NON-NLS + LOGGER.log(Level.SEVERE, "Error connecting to central repository database.", ex); // NON-NLS + throw new IngestModuleException("Error connecting to central repository database.", ex); // NON-NLS } try { @@ -289,9 +290,9 @@ class IngestModule implements FileIngestModule { String MODULE_NAME = IngestModuleFactory.getModuleName(); BlackboardArtifact tifArtifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT); BlackboardAttribute att = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, - Bundle.IngestModule_prevcases_text()); + Bundle.IngestModule_prevTaggedSet_text()); BlackboardAttribute att2 = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, MODULE_NAME, - "Previous Case: " + caseDisplayNames.stream().distinct().collect(Collectors.joining(",", "", ""))); + Bundle.IngestModule_prevCaseComment_text() + caseDisplayNames.stream().distinct().collect(Collectors.joining(",", "", ""))); tifArtifact.addAttribute(att); tifArtifact.addAttribute(att2); @@ -319,7 +320,7 @@ class IngestModule implements FileIngestModule { String MODULE_NAME = IngestModuleFactory.getModuleName(); BlackboardArtifact tifArtifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT); BlackboardAttribute att = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, - Bundle.IngestModule_prevcases_text()); + Bundle.IngestModule_prevCaseComment_text()); tifArtifact.addAttribute(att); try { diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties index 5e0831e130..e15accaff1 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties @@ -8,7 +8,7 @@ EamPostgresSettingsDialog.bnCancel.text=Cancel EamPostgresSettingsDialog.lbPort.text=Port : EamPostgresSettingsDialog.lbHostName.text=Host Name / IP : EamPostgresSettingsDialog.bnTestConnection.text=Test Connection -EamPostgresSettingsDialog.lbDatabaseName.text=Database name : +EamPostgresSettingsDialog.lbDatabaseName.text=Database Name : EamSqliteSettingsDialog.bnCancel.text=Cancel EamSqliteSettingsDialog.lbTestDatabase.text= EamSqliteSettingsDialog.bnTestDatabase.text=Test Connection diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java index 8fb0bfe236..cf4d09b614 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java @@ -59,7 +59,7 @@ public class EamDbSettingsDialog extends JDialog { */ @Messages({"EamDbSettingsDialog.title.text=Central Repository Database Configuration", "EamDbSettingsDialog.lbSingleUserSqLite.text=SQLite should only be used by one examiner at a time.", - "EamDbSettingsDialog.lbDatabaseType.text=Database type :", + "EamDbSettingsDialog.lbDatabaseType.text=Database Type :", "EamDbSettingsDialog.fcDatabasePath.title=Select location for central_repository.db"}) public EamDbSettingsDialog() { @@ -94,7 +94,7 @@ public class EamDbSettingsDialog extends JDialog { @Override public String getDescription() { - return "Directories and Central Repository databases"; + return "Directories and central repository databases"; } }); cbDatabaseType.setSelectedItem(selectedPlatform); @@ -419,7 +419,7 @@ public class EamDbSettingsDialog extends JDialog { Bundle.EamDbSettingsDialog_okButton_createPostgresDbError_message(), Bundle.EamDbSettingsDialog_okButton_createDbError_title(), JOptionPane.WARNING_MESSAGE); - LOGGER.severe("Unable to initialize database schema or insert contents into Central Repository."); + LOGGER.severe("Unable to initialize database schema or insert contents into central repository."); return; } break; @@ -440,7 +440,7 @@ public class EamDbSettingsDialog extends JDialog { Bundle.EamDbSettingsDialog_okButton_createSQLiteDbError_message(), Bundle.EamDbSettingsDialog_okButton_createDbError_title(), JOptionPane.WARNING_MESSAGE); - LOGGER.severe("Unable to initialize database schema or insert contents into Central Repository."); + LOGGER.severe("Unable to initialize database schema or insert contents into central repository."); return; } break; @@ -459,7 +459,7 @@ public class EamDbSettingsDialog extends JDialog { @Messages({"EamDbSettingsDialog.okButton.errorTitle.text=Restart Required.", "EamDbSettingsDialog.okButton.errorMsg.text=Please restart Autopsy to begin using the new database platform.", - "EamDbSettingsDialog.okButton.connectionErrorMsg.text=Failed to connect to Central Repository database.", + "EamDbSettingsDialog.okButton.connectionErrorMsg.text=Failed to connect to central repository database.", "EamDbSettingsDialog.okButton.corruptDatabaseExists.title=Error Loading Database", "EamDbSettingsDialog.okButton.corruptDatabaseExists.message=Database exists but is not the right format. Manually delete it or choose a different path (if applicable).", "EamDbSettingsDialog.okButton.createDbDialog.title=Database Does Not Exist", diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.form index 2e87f1d5a4..c9c19a90ff 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.form @@ -19,32 +19,46 @@ - + - - - - - + + + + + + + + + + + + + + + - + + - - - + + + + + + + - - - + + @@ -66,26 +80,26 @@ - + - + + + + + - - - - - - - + + + + + - - @@ -107,9 +121,9 @@ - + - + @@ -154,53 +168,81 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - + + + + + + + + + + - - - - - - - - + + + + + + - - - - - - - - - - - - - - - - @@ -217,16 +259,42 @@ - + - - + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -244,16 +312,108 @@ + + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java index 7e231d7cd2..ad065f156d 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java @@ -41,7 +41,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i private static final long serialVersionUID = 1L; private static final Logger LOGGER = Logger.getLogger(GlobalSettingsPanel.class.getName()); - + private final IngestJobEventPropertyChangeListener ingestJobEventListener; /** @@ -56,7 +56,14 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i } @Messages({"GlobalSettingsPanel.title=Central Repository Settings", - "GlobalSettingsPanel.cbUseCentralRepo.text=Use a Central Repository"}) + "GlobalSettingsPanel.cbUseCentralRepo.text=Use a central repository", + "GlobalSettingsPanel.pnTagManagement.border.title=Tags", + "GlobalSettingsPanel.pnCorrelationProperties.border.title=Correlation Properties", + "GlobalSettingsPanel.lbCentralRepository.text=A central repository allows you to correlate files and results between cases.", + "GlobalSettingsPanel.manageTagsTextArea.text=Configure which tag names are associated with notable or known bad items. " + + "When these tags are used, the file or result will be recorded in the central repository. " + + "If that file or result is seen again in future cases, it will be flagged.", + "GlobalSettingsPanel.correlationPropertiesTextArea.text=Choose which file and result properties to store in the central central repository for later correlation."}) private void customizeComponents() { setName(Bundle.GlobalSettingsPanel_title()); @@ -86,12 +93,18 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i lbDbPlatformValue = new javax.swing.JLabel(); lbDbNameValue = new javax.swing.JLabel(); lbDbLocationValue = new javax.swing.JLabel(); - pnDatabaseContentButtons = new javax.swing.JPanel(); - bnImportDatabase = new javax.swing.JButton(); - bnManageTags = new javax.swing.JButton(); - bnManageTypes = new javax.swing.JButton(); - tbOops = new javax.swing.JTextField(); cbUseCentralRepo = new javax.swing.JCheckBox(); + bnImportDatabase = new javax.swing.JButton(); + pnTagManagement = new javax.swing.JPanel(); + bnManageTags = new javax.swing.JButton(); + manageTagsScrollPane = new javax.swing.JScrollPane(); + manageTagsTextArea = new javax.swing.JTextArea(); + tbOops = new javax.swing.JTextField(); + pnCorrelationProperties = new javax.swing.JPanel(); + bnManageTypes = new javax.swing.JButton(); + correlationPropertiesScrollPane = new javax.swing.JScrollPane(); + correlationPropertiesTextArea = new javax.swing.JTextArea(); + lbCentralRepository = new javax.swing.JLabel(); setName(""); // NOI18N @@ -117,19 +130,19 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i .addGroup(pnDatabaseConfigurationLayout.createSequentialGroup() .addContainerGap() .addGroup(pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnDatabaseConfigurationLayout.createSequentialGroup() + .addComponent(bnDbConfigure) + .addContainerGap()) .addGroup(pnDatabaseConfigurationLayout.createSequentialGroup() .addGroup(pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(lbDbPlatformTypeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(lbDbNameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(lbDbLocationLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 57, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(lbDbPlatformValue, javax.swing.GroupLayout.PREFERRED_SIZE, 711, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lbDbNameValue, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 711, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(lbDbLocationValue, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 711, javax.swing.GroupLayout.PREFERRED_SIZE))) - .addComponent(bnDbConfigure)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(lbDbNameValue, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(lbDbPlatformValue, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(lbDbLocationValue, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))) ); pnDatabaseConfigurationLayout.setVerticalGroup( pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -146,11 +159,18 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i .addGroup(pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(lbDbLocationLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(lbDbLocationValue, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 11, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(bnDbConfigure) - .addContainerGap()) + .addGap(8, 8, 8)) ); + org.openide.awt.Mnemonics.setLocalizedText(cbUseCentralRepo, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.cbUseCentralRepo.text")); // NOI18N + cbUseCentralRepo.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cbUseCentralRepoActionPerformed(evt); + } + }); + bnImportDatabase.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/centralrepository/images/import16.png"))); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnImportDatabase, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnImportDatabase.label")); // NOI18N bnImportDatabase.setActionCommand(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnImportDatabase.actionCommand")); // NOI18N @@ -160,6 +180,9 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i } }); + pnTagManagement.setBorder(javax.swing.BorderFactory.createTitledBorder(null, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.pnTagManagement.border.title"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 0, 12))); // NOI18N + pnTagManagement.setPreferredSize(new java.awt.Dimension(674, 97)); + org.openide.awt.Mnemonics.setLocalizedText(bnManageTags, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnManageTags.text")); // NOI18N bnManageTags.setToolTipText(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnManageTags.toolTipText")); // NOI18N bnManageTags.setActionCommand(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnManageTags.actionCommand")); // NOI18N @@ -169,6 +192,57 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i } }); + manageTagsScrollPane.setBorder(null); + + manageTagsTextArea.setEditable(false); + manageTagsTextArea.setBackground(new java.awt.Color(240, 240, 240)); + manageTagsTextArea.setColumns(20); + manageTagsTextArea.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N + manageTagsTextArea.setLineWrap(true); + manageTagsTextArea.setRows(2); + manageTagsTextArea.setText(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.manageTagsTextArea.text")); // NOI18N + manageTagsTextArea.setToolTipText(""); + manageTagsTextArea.setWrapStyleWord(true); + manageTagsTextArea.setBorder(null); + manageTagsScrollPane.setViewportView(manageTagsTextArea); + + javax.swing.GroupLayout pnTagManagementLayout = new javax.swing.GroupLayout(pnTagManagement); + pnTagManagement.setLayout(pnTagManagementLayout); + pnTagManagementLayout.setHorizontalGroup( + pnTagManagementLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnTagManagementLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnTagManagementLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnTagManagementLayout.createSequentialGroup() + .addComponent(bnManageTags) + .addGap(0, 555, Short.MAX_VALUE)) + .addGroup(pnTagManagementLayout.createSequentialGroup() + .addComponent(manageTagsScrollPane) + .addContainerGap()))) + ); + pnTagManagementLayout.setVerticalGroup( + pnTagManagementLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnTagManagementLayout.createSequentialGroup() + .addGap(7, 7, 7) + .addComponent(manageTagsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 31, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(bnManageTags, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(8, 8, 8)) + ); + + tbOops.setEditable(false); + tbOops.setFont(tbOops.getFont().deriveFont(tbOops.getFont().getStyle() | java.awt.Font.BOLD, 12)); + tbOops.setText(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.tbOops.text")); // NOI18N + tbOops.setBorder(null); + tbOops.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + tbOopsActionPerformed(evt); + } + }); + + pnCorrelationProperties.setBorder(javax.swing.BorderFactory.createTitledBorder(null, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.pnCorrelationProperties.border.title"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 0, 12))); // NOI18N + pnCorrelationProperties.setPreferredSize(new java.awt.Dimension(674, 93)); + org.openide.awt.Mnemonics.setLocalizedText(bnManageTypes, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnManageProperties.text")); // NOI18N bnManageTypes.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -176,41 +250,44 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i } }); - javax.swing.GroupLayout pnDatabaseContentButtonsLayout = new javax.swing.GroupLayout(pnDatabaseContentButtons); - pnDatabaseContentButtons.setLayout(pnDatabaseContentButtonsLayout); - pnDatabaseContentButtonsLayout.setHorizontalGroup( - pnDatabaseContentButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnDatabaseContentButtonsLayout.createSequentialGroup() + correlationPropertiesScrollPane.setBorder(null); + + correlationPropertiesTextArea.setEditable(false); + correlationPropertiesTextArea.setBackground(new java.awt.Color(240, 240, 240)); + correlationPropertiesTextArea.setColumns(20); + correlationPropertiesTextArea.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N + correlationPropertiesTextArea.setLineWrap(true); + correlationPropertiesTextArea.setRows(2); + correlationPropertiesTextArea.setText(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.correlationPropertiesTextArea.text")); // NOI18N + correlationPropertiesTextArea.setToolTipText(""); + correlationPropertiesTextArea.setWrapStyleWord(true); + correlationPropertiesTextArea.setBorder(null); + correlationPropertiesScrollPane.setViewportView(correlationPropertiesTextArea); + + javax.swing.GroupLayout pnCorrelationPropertiesLayout = new javax.swing.GroupLayout(pnCorrelationProperties); + pnCorrelationProperties.setLayout(pnCorrelationPropertiesLayout); + pnCorrelationPropertiesLayout.setHorizontalGroup( + pnCorrelationPropertiesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnCorrelationPropertiesLayout.createSequentialGroup() .addContainerGap() - .addComponent(bnImportDatabase) + .addGroup(pnCorrelationPropertiesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(correlationPropertiesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 642, Short.MAX_VALUE) + .addGroup(pnCorrelationPropertiesLayout.createSequentialGroup() + .addComponent(bnManageTypes) + .addGap(0, 0, Short.MAX_VALUE))) + .addContainerGap()) + ); + pnCorrelationPropertiesLayout.setVerticalGroup( + pnCorrelationPropertiesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnCorrelationPropertiesLayout.createSequentialGroup() + .addGap(7, 7, 7) + .addComponent(correlationPropertiesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(bnManageTags) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(bnManageTypes) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - ); - pnDatabaseContentButtonsLayout.setVerticalGroup( - pnDatabaseContentButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnDatabaseContentButtonsLayout.createSequentialGroup() - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(pnDatabaseContentButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(bnImportDatabase) - .addComponent(bnManageTags, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(bnManageTypes, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGap(34, 34, 34)) + .addGap(8, 8, 8)) ); - tbOops.setEditable(false); - tbOops.setFont(tbOops.getFont().deriveFont(tbOops.getFont().getStyle() | java.awt.Font.BOLD, 12)); - tbOops.setText(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.tbOops.text")); // NOI18N - tbOops.setBorder(null); - - org.openide.awt.Mnemonics.setLocalizedText(cbUseCentralRepo, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.cbUseCentralRepo.text")); // NOI18N - cbUseCentralRepo.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - cbUseCentralRepoActionPerformed(evt); - } - }); + org.openide.awt.Mnemonics.setLocalizedText(lbCentralRepository, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.lbCentralRepository.text")); // NOI18N javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); @@ -219,26 +296,39 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(pnDatabaseContentButtons, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(tbOops, javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(pnDatabaseConfiguration, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(layout.createSequentialGroup() - .addComponent(cbUseCentralRepo, javax.swing.GroupLayout.PREFERRED_SIZE, 186, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, Short.MAX_VALUE))) - .addContainerGap()) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(lbCentralRepository, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pnCorrelationProperties, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pnTagManagement, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pnDatabaseConfiguration, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(cbUseCentralRepo, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 186, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(bnImportDatabase, javax.swing.GroupLayout.Alignment.LEADING)) + .addGap(0, 0, Short.MAX_VALUE))) + .addContainerGap()))) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(lbCentralRepository) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(cbUseCentralRepo) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(pnDatabaseConfiguration, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pnDatabaseConfiguration, javax.swing.GroupLayout.PREFERRED_SIZE, 119, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(pnTagManagement, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(pnCorrelationProperties, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) .addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pnDatabaseContentButtons, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap()) + .addGap(0, 0, 0) + .addComponent(bnImportDatabase)) ); + + pnTagManagement.getAccessibleContext().setAccessibleName(""); }// //GEN-END:initComponents private void bnImportDatabaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnImportDatabaseActionPerformed @@ -276,6 +366,10 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); }//GEN-LAST:event_cbUseCentralRepoActionPerformed + private void tbOopsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tbOopsActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_tbOopsActionPerformed + @Override @Messages({"GlobalSettingsPanel.validationerrMsg.mustConfigure=Configure the database to enable this module."}) public void load() { @@ -398,7 +492,6 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i private void enableDatabaseConfigureButton(Boolean enable) { boolean ingestRunning = IngestManager.getInstance().isIngestRunning(); pnDatabaseConfiguration.setEnabled(enable && !ingestRunning); - pnDatabaseContentButtons.setEnabled(enable && !ingestRunning); bnDbConfigure.setEnabled(enable && !ingestRunning); lbDbLocationLabel.setEnabled(enable && !ingestRunning); lbDbLocationValue.setEnabled(enable && !ingestRunning); @@ -418,10 +511,14 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i * @return True */ private boolean enableButtonSubComponents(Boolean enable) { - boolean ingestRunning = IngestManager.getInstance().isIngestRunning(); + boolean ingestRunning = IngestManager.getInstance().isIngestRunning(); + pnCorrelationProperties.setEnabled(enable && !ingestRunning); + pnTagManagement.setEnabled(enable && !ingestRunning); bnManageTypes.setEnabled(enable && !ingestRunning); bnImportDatabase.setEnabled(enable && !ingestRunning); bnManageTags.setEnabled(enable && !ingestRunning); + manageTagsTextArea.setEnabled(enable && !ingestRunning); + correlationPropertiesTextArea.setEnabled(enable && !ingestRunning); return true; } @@ -431,14 +528,20 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i private javax.swing.JButton bnManageTags; private javax.swing.JButton bnManageTypes; private javax.swing.JCheckBox cbUseCentralRepo; + private javax.swing.JScrollPane correlationPropertiesScrollPane; + private javax.swing.JTextArea correlationPropertiesTextArea; + private javax.swing.JLabel lbCentralRepository; private javax.swing.JLabel lbDbLocationLabel; private javax.swing.JLabel lbDbLocationValue; private javax.swing.JLabel lbDbNameLabel; private javax.swing.JLabel lbDbNameValue; private javax.swing.JLabel lbDbPlatformTypeLabel; private javax.swing.JLabel lbDbPlatformValue; + private javax.swing.JScrollPane manageTagsScrollPane; + private javax.swing.JTextArea manageTagsTextArea; + private javax.swing.JPanel pnCorrelationProperties; private javax.swing.JPanel pnDatabaseConfiguration; - private javax.swing.JPanel pnDatabaseContentButtons; + private javax.swing.JPanel pnTagManagement; private javax.swing.JTextField tbOops; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ImportHashDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ImportHashDatabaseDialog.java index 2eccb89ec9..ad2a9bd54b 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ImportHashDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ImportHashDatabaseDialog.java @@ -587,7 +587,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { this.progress = ProgressHandle.createHandle(Bundle.ImportHashDatabaseDialog_ImportHashDatabaseWorker_displayName()); if (!EamDb.isEnabled()) { - throw new EamDbException("Central Repository database is not enabled."); // NON-NLS + throw new EamDbException("Central repository database is not enabled."); // NON-NLS } } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageCorrelationPropertiesDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageCorrelationPropertiesDialog.java index 727083c205..0d45c51d2f 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageCorrelationPropertiesDialog.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageCorrelationPropertiesDialog.java @@ -249,7 +249,7 @@ final class ManageCorrelationPropertiesDialog extends javax.swing.JDialog { try { dbManager = EamDb.getInstance(); } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Failed to connect to Central Repository database.", ex); + LOGGER.log(Level.SEVERE, "Failed to connect to central repository database.", ex); lbWarningMsg.setText(Bundle.ManageCorrelationPropertiesDialog_okbutton_failure()); return; } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.form b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.form index 07be8010cd..f1ad5a38e4 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.form +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.form @@ -31,17 +31,18 @@ - + - - - - + + + + + - + @@ -51,16 +52,18 @@ - - - - - + + + + + + + - + @@ -86,7 +89,7 @@ - + @@ -97,8 +100,8 @@ - - + +
@@ -107,5 +110,38 @@
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.java index 49d9ab6d79..01d984bda0 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.java @@ -60,25 +60,34 @@ final class ManageTagsDialog extends javax.swing.JDialog { * and add it to the set of hash databases used to classify files as * unknown, known, or known bad. */ - @Messages({"ManageTagDialog.title=Manage Tags"}) + @Messages({"ManageTagDialog.title=Manage Tags", + "ManageTagDialog.tagInfo.text=Select the tags that cause files and results to be recorded in the central repository. Additional tags can be created in the Tags options panel."}) ManageTagsDialog() { super((JFrame) WindowManager.getDefault().getMainWindow(), Bundle.ManageTagDialog_title(), true); // NON-NLS initComponents(); customizeComponents(); + setupHelpTextArea(); display(); } - @Messages({"ManageTagsDialog.init.failedConnection.msg=Cannot connect to Central Repository.", - "ManageTagsDialog.init.failedGettingTags.msg=Unable to retrieve list of tags."}) + + @Messages({"ManageTagsDialog.init.failedConnection.msg=Cannot connect to central cepository.", + "ManageTagsDialog.init.failedGettingTags.msg=Unable to retrieve list of tags.", + "ManageTagsDialog.tagColumn.header.text=Tags", + "ManageTagsDialog.notableColumn.header.text=Notable"}) + private void setupHelpTextArea() { + helpTextArea.setText(Bundle.ManageTagDialog_tagInfo_text()); + } + private void customizeComponents() { lbWarnings.setText(""); EamDb dbManager; try { dbManager = EamDb.getInstance(); } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Failed to connect to Central Repository database."); + LOGGER.log(Level.SEVERE, "Failed to connect to central repository database."); lbWarnings.setText(Bundle.ManageTagsDialog_init_failedConnection_msg()); return; } @@ -99,6 +108,7 @@ final class ManageTagsDialog extends javax.swing.JDialog { Collections.sort(tagNames); DefaultTableModel model = (DefaultTableModel) tblTagNames.getModel(); + model.setColumnIdentifiers(new String[] {Bundle.ManageTagsDialog_tagColumn_header_text(), Bundle.ManageTagsDialog_notableColumn_header_text()}); for (String tagName : tagNames) { boolean enabled = badTags.contains(tagName); model.addRow(new Object[]{tagName, enabled}); @@ -125,9 +135,11 @@ final class ManageTagsDialog extends javax.swing.JDialog { buttonGroup1 = new javax.swing.ButtonGroup(); okButton = new javax.swing.JButton(); cancelButton = new javax.swing.JButton(); - jScrollPane1 = new javax.swing.JScrollPane(); + tagScrollArea = new javax.swing.JScrollPane(); tblTagNames = new javax.swing.JTable(); lbWarnings = new javax.swing.JLabel(); + helpScrollPane = new javax.swing.JScrollPane(); + helpTextArea = new javax.swing.JTextArea(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); @@ -150,7 +162,7 @@ final class ManageTagsDialog extends javax.swing.JDialog { }, new String [] { - "Tag", "Implies Known Bad" + "", "" } ) { Class[] types = new Class [] { @@ -168,7 +180,20 @@ final class ManageTagsDialog extends javax.swing.JDialog { return canEdit [columnIndex]; } }); - jScrollPane1.setViewportView(tblTagNames); + tagScrollArea.setViewportView(tblTagNames); + + helpScrollPane.setBorder(null); + + helpTextArea.setEditable(false); + helpTextArea.setBackground(new java.awt.Color(240, 240, 240)); + helpTextArea.setColumns(20); + helpTextArea.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N + helpTextArea.setLineWrap(true); + helpTextArea.setRows(3); + helpTextArea.setWrapStyleWord(true); + helpTextArea.setBorder(null); + helpTextArea.setFocusable(false); + helpScrollPane.setViewportView(helpTextArea); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); @@ -178,15 +203,16 @@ final class ManageTagsDialog extends javax.swing.JDialog { .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addGap(0, 223, Short.MAX_VALUE) + .addGap(0, 0, Short.MAX_VALUE) .addComponent(okButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(cancelButton)) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 357, Short.MAX_VALUE) - .addComponent(lbWarnings, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addGap(0, 0, Short.MAX_VALUE))) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(helpScrollPane, javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(tagScrollArea, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 328, Short.MAX_VALUE) + .addComponent(lbWarnings, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGap(2, 2, 2))) .addContainerGap()) ); @@ -196,9 +222,11 @@ final class ManageTagsDialog extends javax.swing.JDialog { layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addContainerGap() - .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 335, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(lbWarnings, javax.swing.GroupLayout.DEFAULT_SIZE, 16, Short.MAX_VALUE) + .addComponent(helpScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(tagScrollArea, javax.swing.GroupLayout.DEFAULT_SIZE, 341, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lbWarnings, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(okButton) @@ -237,7 +265,7 @@ final class ManageTagsDialog extends javax.swing.JDialog { dbManager.setBadTags(badTags); dbManager.saveSettings(); } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Failed to connect to Central Repository database."); // NON-NLS + LOGGER.log(Level.SEVERE, "Failed to connect to central repository database."); // NON-NLS lbWarnings.setText(Bundle.ManageTagsDialog_init_failedConnection_msg()); return false; } @@ -249,9 +277,9 @@ final class ManageTagsDialog extends javax.swing.JDialog { * any existing tagged items (in the current case only) in the central repo. */ public class CheckBoxModelListener implements TableModelListener { - @Messages({"ManageTagsDialog.updateCurrentCase.msg=Mark as known bad any files/artifacts in the current case that have this tag?", + @Messages({"ManageTagsDialog.updateCurrentCase.msg=Mark as known bad any files/results in the current case that have this tag?", "ManageTagsDialog.updateCurrentCase.title=Update current case?", - "ManageTagsDialog.updateCurrentCase.error=Error updating existing Central Repository entries"}) + "ManageTagsDialog.updateCurrentCase.error=Error updating existing central repository entries"}) javax.swing.JDialog dialog; public CheckBoxModelListener(javax.swing.JDialog dialog){ @@ -331,9 +359,11 @@ final class ManageTagsDialog extends javax.swing.JDialog { // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.ButtonGroup buttonGroup1; private javax.swing.JButton cancelButton; - private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JScrollPane helpScrollPane; + private javax.swing.JTextArea helpTextArea; private javax.swing.JLabel lbWarnings; private javax.swing.JButton okButton; + private javax.swing.JScrollPane tagScrollArea; private javax.swing.JTable tblTagNames; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java b/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java index 074e7f162e..c908f3b35d 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java @@ -19,27 +19,16 @@ package org.sleuthkit.autopsy.corecomponents; import java.awt.Insets; -import java.io.File; -import java.util.Collection; import java.util.Map; import java.util.TreeMap; import java.util.logging.Level; import javax.swing.BorderFactory; -import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UIManager.LookAndFeelInfo; import javax.swing.UnsupportedLookAndFeelException; -import org.netbeans.spi.sendopts.OptionProcessor; import org.netbeans.swing.tabcontrol.plaf.DefaultTabbedContainerUI; import org.openide.modules.ModuleInstall; -import org.openide.util.Lookup; -import org.openide.util.NbBundle; import org.openide.windows.WindowManager; -import org.sleuthkit.autopsy.actions.IngestRunningCheck; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.CaseActionException; -import org.sleuthkit.autopsy.casemodule.CaseMetadata; -import org.sleuthkit.autopsy.casemodule.OpenFromArguments; import org.sleuthkit.autopsy.casemodule.StartupWindowProvider; import org.sleuthkit.autopsy.coreutils.Logger; @@ -66,33 +55,11 @@ public class Installer extends ModuleInstall { @Override public void restored() { super.restored(); - setLookAndFeel(); UIManager.put("ViewTabDisplayerUI", "org.sleuthkit.autopsy.corecomponents.NoTabsTabDisplayerUI"); UIManager.put(DefaultTabbedContainerUI.KEY_VIEW_CONTENT_BORDER, BorderFactory.createEmptyBorder()); UIManager.put("TabbedPane.contentBorderInsets", new Insets(0, 0, 0, 0)); - - /* - * Open the case if a case metadata file was double-clicked. This only - * works if the user has associated files with ".aut" extensions with - * Autopsy. - */ WindowManager.getDefault().invokeWhenUIReady(() -> { - Collection processors = Lookup.getDefault().lookupAll(OptionProcessor.class); - for (OptionProcessor processor : processors) { - if (processor instanceof OpenFromArguments) { - OpenFromArguments argsProcessor = (OpenFromArguments) processor; - final String caseFile = argsProcessor.getDefaultArg(); - if (caseFile != null && !caseFile.isEmpty() && caseFile.endsWith(CaseMetadata.getFileExtension()) && new File(caseFile).exists()) { //NON-NLS - try { - Case.openAsCurrentCase(caseFile); - } catch (CaseActionException ex) { - logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseFile), ex); //NON-NLS - } - return; - } - } - } StartupWindowProvider.getInstance().open(); }); } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index 8f80022834..aa9201efc7 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -1143,7 +1143,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { } tableModel.setRowCount(0); for (AutoIngestJob job : jobs) { - AutoIngestJob.StageDetails status = job.getStageDetails(); + AutoIngestJob.StageDetails status = job.getProcessingStageDetails(); tableModel.addRow(new Object[]{ job.getManifest().getCaseName(), // CASE job.getManifest().getDataSourcePath().getFileName(), // DATA_SOURCE @@ -1152,7 +1152,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { job.getProcessingStageStartDate(), // STARTED_TIME job.getCompletedDate(), // COMPLETED_TIME status.getDescription(), // ACTIVITY -job.getErrorsOccurred(), // STATUS + job.getErrorsOccurred(), // STATUS ((Date.from(Instant.now()).getTime()) - (status.getStartDate().getTime())), // ACTIVITY_TIME job.getCaseDirectoryPath(), // CASE_DIRECTORY_PATH job.getProcessingHostName().equals(LOCAL_HOST_NAME), // IS_LOCAL_JOB @@ -1701,7 +1701,7 @@ job.getErrorsOccurred(), // STATUS * * @param evt The button click event. */ - @Messages({"AutoIngestControlPanel.casePrioritization.errorMessage=An error occurred when prioritizing the case. Some or all jobs may not have been prioritized."}) + @Messages({"AutoIngestControlPanel.casePrioritization.errorMessage=An error occurred when prioritizing the case. Some or all jobs may not have been prioritized."}) private void bnPrioritizeCaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnPrioritizeCaseActionPerformed if (pendingTableModel.getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) { this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); @@ -1759,8 +1759,8 @@ job.getErrorsOccurred(), // STATUS options[0]); } }//GEN-LAST:event_bnShowCaseLogActionPerformed - - @Messages({"AutoIngestControlPanel.jobPrioritization.errorMessage=An error occurred when prioritizing the job."}) + + @Messages({"AutoIngestControlPanel.jobPrioritization.errorMessage=An error occurred when prioritizing the job."}) private void bnPrioritizeJobActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnPrioritizeJobActionPerformed if (pendingTableModel.getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) { this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java index 6782140e7e..213ca60d23 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.experimental.autoingest; +import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.awt.Cursor; import java.awt.EventQueue; import java.nio.file.Path; @@ -44,6 +45,8 @@ import org.sleuthkit.autopsy.core.ServicesMonitor; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestMonitor.JobsSnapshot; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; /** * A dashboard for monitoring an automated ingest cluster. @@ -55,28 +58,30 @@ public final class AutoIngestDashboard extends JPanel implements Observer { private static final int GENERIC_COL_MAX_WIDTH = 2000; private static final int PENDING_TABLE_COL_PREFERRED_WIDTH = 280; private static final int RUNNING_TABLE_COL_PREFERRED_WIDTH = 175; - private static final int ACTIVITY_TIME_COL_MIN_WIDTH = 250; - private static final int ACTIVITY_TIME_COL_MAX_WIDTH = 450; + private static final int STAGE_TIME_COL_MIN_WIDTH = 250; + private static final int STAGE_TIME_COL_MAX_WIDTH = 450; private static final int TIME_COL_MIN_WIDTH = 30; private static final int TIME_COL_MAX_WIDTH = 250; private static final int TIME_COL_PREFERRED_WIDTH = 140; private static final int NAME_COL_MIN_WIDTH = 100; private static final int NAME_COL_MAX_WIDTH = 250; private static final int NAME_COL_PREFERRED_WIDTH = 140; - private static final int ACTIVITY_COL_MIN_WIDTH = 70; - private static final int ACTIVITY_COL_MAX_WIDTH = 2000; - private static final int ACTIVITY_COL_PREFERRED_WIDTH = 300; + private static final int STAGE_COL_MIN_WIDTH = 70; + private static final int STAGE_COL_MAX_WIDTH = 2000; + private static final int STAGE_COL_PREFERRED_WIDTH = 300; private static final int STATUS_COL_MIN_WIDTH = 55; private static final int STATUS_COL_MAX_WIDTH = 250; private static final int STATUS_COL_PREFERRED_WIDTH = 55; private static final int COMPLETED_TIME_COL_MIN_WIDTH = 30; private static final int COMPLETED_TIME_COL_MAX_WIDTH = 2000; private static final int COMPLETED_TIME_COL_PREFERRED_WIDTH = 280; + private static final String UPDATE_TASKS_THREAD_NAME = "AID-update-tasks-%d"; private static final Logger logger = Logger.getLogger(AutoIngestDashboard.class.getName()); private final DefaultTableModel pendingTableModel; private final DefaultTableModel runningTableModel; private final DefaultTableModel completedTableModel; private AutoIngestMonitor autoIngestMonitor; + private ExecutorService updateExecutor; /** * Creates a dashboard for monitoring an automated ingest cluster. @@ -213,6 +218,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer { pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader())); pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.STATUS.getColumnHeader())); pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader())); + pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.JOB.getColumnHeader())); /* * Set up a column to display the cases associated with the jobs. @@ -275,6 +281,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer { runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.STATUS.getColumnHeader())); runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader())); runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader())); + runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.JOB.getColumnHeader())); /* * Set up a column to display the cases associated with the jobs. @@ -311,10 +318,10 @@ public final class AutoIngestDashboard extends JPanel implements Observer { * jobs. */ column = runningTable.getColumn(JobsTableModelColumns.STAGE.getColumnHeader()); - column.setMinWidth(ACTIVITY_COL_MIN_WIDTH); - column.setMaxWidth(ACTIVITY_COL_MAX_WIDTH); - column.setPreferredWidth(ACTIVITY_COL_PREFERRED_WIDTH); - column.setWidth(ACTIVITY_COL_PREFERRED_WIDTH); + column.setMinWidth(STAGE_COL_MIN_WIDTH); + column.setMaxWidth(STAGE_COL_MAX_WIDTH); + column.setPreferredWidth(STAGE_COL_PREFERRED_WIDTH); + column.setWidth(STAGE_COL_PREFERRED_WIDTH); /* * Set up a column to display the ingest activity times associated with @@ -323,9 +330,9 @@ public final class AutoIngestDashboard extends JPanel implements Observer { column = runningTable.getColumn(JobsTableModelColumns.STAGE_TIME.getColumnHeader()); column.setCellRenderer(new DurationCellRenderer()); column.setMinWidth(GENERIC_COL_MIN_WIDTH); - column.setMaxWidth(ACTIVITY_TIME_COL_MAX_WIDTH); - column.setPreferredWidth(ACTIVITY_TIME_COL_MIN_WIDTH); - column.setWidth(ACTIVITY_TIME_COL_MIN_WIDTH); + column.setMaxWidth(STAGE_TIME_COL_MAX_WIDTH); + column.setPreferredWidth(STAGE_TIME_COL_MIN_WIDTH); + column.setWidth(STAGE_TIME_COL_MIN_WIDTH); /* * Prevent sorting when a column header is clicked. @@ -348,6 +355,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer { completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.HOST_NAME.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader())); + completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.JOB.getColumnHeader())); /* * Set up a column to display the cases associated with the jobs. @@ -419,12 +427,20 @@ public final class AutoIngestDashboard extends JPanel implements Observer { autoIngestMonitor = new AutoIngestMonitor(); autoIngestMonitor.addObserver(this); autoIngestMonitor.startUp(); + updateExecutor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(UPDATE_TASKS_THREAD_NAME).build()); + updateExecutor.submit(new UpdateJobsSnapshotTask()); } @Override - public void update(Observable observable, Object argument) { - JobsSnapshot jobsSnapshot = (JobsSnapshot) argument; - EventQueue.invokeLater(new RefreshComponentsTask(jobsSnapshot)); + public void update(Observable observable, Object arg) { + /* + * By creating a task to get the latest jobs snapshot, the possibility + * of queuing a refresh task for the EDT with snaphot rendered stale by + * the handling of a user prioritization action, etc. on the EDT is + * avoided. This is why the snapshot pushed ny the auto ingest jobs + * monitor is ignored. + */ + updateExecutor.submit(new UpdateJobsSnapshotTask()); } /** @@ -438,7 +454,6 @@ public final class AutoIngestDashboard extends JPanel implements Observer { List runningJobs = jobsSnapshot.getRunningJobs(); List completedJobs = jobsSnapshot.getCompletedJobs(); pendingJobs.sort(new AutoIngestJob.PriorityComparator()); - runningJobs.sort(new AutoIngestJob.CaseNameAndProcessingHostComparator()); completedJobs.sort(new AutoIngestJob.ReverseCompletedDateComparator()); refreshTable(pendingJobs, pendingTable, pendingTableModel); refreshTable(runningJobs, runningTable, runningTableModel); @@ -459,24 +474,19 @@ public final class AutoIngestDashboard extends JPanel implements Observer { Path currentRow = getSelectedEntry(table, tableModel); tableModel.setRowCount(0); for (AutoIngestJob job : jobs) { - if (job.getVersion() < 1) { - // Ignore version '0' nodes since they don't carry enough - // data to populate the table. - continue; - } - AutoIngestJob.StageDetails status = job.getStageDetails(); + AutoIngestJob.StageDetails status = job.getProcessingStageDetails(); tableModel.addRow(new Object[]{ job.getManifest().getCaseName(), // CASE job.getManifest().getDataSourcePath().getFileName(), job.getProcessingHostName(), // HOST_NAME job.getManifest().getDateFileCreated(), // CREATED_TIME job.getProcessingStageStartDate(), // STARTED_TIME job.getCompletedDate(), // COMPLETED_TIME - status.getDescription(), // ACTIVITY + status.getDescription(), // STAGE job.getErrorsOccurred(), // STATUS - ((Date.from(Instant.now()).getTime()) - (status.getStartDate().getTime())), // ACTIVITY_TIME + ((Date.from(Instant.now()).getTime()) - (status.getStartDate().getTime())), // STAGE_TIME job.getCaseDirectoryPath(), // CASE_DIRECTORY_PATH - job.getManifest().getFilePath() // MANIFEST_FILE_PATH - //DLG: Put job object in the table + job.getManifest().getFilePath(), // MANIFEST_FILE_PATH + job }); } setSelectedEntry(table, tableModel, currentRow); @@ -542,7 +552,6 @@ public final class AutoIngestDashboard extends JPanel implements Observer { */ private enum JobsTableModelColumns { - // DLG: Go through the bundle.properties file and delete any unused key-value pairs. CASE(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Case")), DATA_SOURCE(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.ImageFolder")), HOST_NAME(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.HostName")), @@ -553,8 +562,8 @@ public final class AutoIngestDashboard extends JPanel implements Observer { STAGE_TIME(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.StageTime")), STATUS(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Status")), CASE_DIRECTORY_PATH(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.CaseFolder")), - MANIFEST_FILE_PATH(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.ManifestFilePath")); //DLG:, - //DLG: JOB(""); + MANIFEST_FILE_PATH(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.ManifestFilePath")), + JOB(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Job")); private final String header; @@ -566,15 +575,6 @@ public final class AutoIngestDashboard extends JPanel implements Observer { return header; } - /* - * DLG: We need to add the AutoIngestJob object for the row to the - * table. As a model you can look in AutoIngestControlPanel to see how a - * boolean is stored in a hidden IS_LOCAL_JOB column and do something - * similar for the job. Once youy hjave done that, you can change the - * button event handler for the Prioritize button to make it pass the - * AutoIngestJob to the AutoIngestMonitor instead of the manifest file - * path. - */ private static final String[] headers = { CASE.getColumnHeader(), DATA_SOURCE.getColumnHeader(), @@ -586,11 +586,28 @@ public final class AutoIngestDashboard extends JPanel implements Observer { STATUS.getColumnHeader(), STAGE_TIME.getColumnHeader(), CASE_DIRECTORY_PATH.getColumnHeader(), - MANIFEST_FILE_PATH.getColumnHeader() //DLG: , - //DLG: JOB.getColumnHeader() + MANIFEST_FILE_PATH.getColumnHeader(), + JOB.getColumnHeader() }; }; + /** + * A task that gets the latest auto ingest jobs snapshot from the autop + * ingest monitor and queues a components refresh task for execution in the + * EDT. + */ + private class UpdateJobsSnapshotTask implements Runnable { + + /** + * @inheritDoc + */ + @Override + public void run() { + JobsSnapshot jobsSnapshot = AutoIngestDashboard.this.autoIngestMonitor.getJobsSnapshot(); + EventQueue.invokeLater(new RefreshComponentsTask(jobsSnapshot)); + } + } + /** * A task that refreshes the UI components on this panel to reflect a * snapshot of the pending, running and completed auto ingest jobs lists of @@ -835,13 +852,13 @@ public final class AutoIngestDashboard extends JPanel implements Observer { private void prioritizeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_prioritizeButtonActionPerformed if (pendingTableModel.getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - Path manifestFilePath = (Path) (pendingTableModel.getValueAt(pendingTable.getSelectedRow(), JobsTableModelColumns.MANIFEST_FILE_PATH.ordinal())); + AutoIngestJob job = (AutoIngestJob) (pendingTableModel.getValueAt(pendingTable.getSelectedRow(), JobsTableModelColumns.JOB.ordinal())); JobsSnapshot jobsSnapshot; try { - jobsSnapshot = autoIngestMonitor.prioritizeJob(manifestFilePath); + jobsSnapshot = autoIngestMonitor.prioritizeJob(job); refreshTables(jobsSnapshot); } catch (AutoIngestMonitor.AutoIngestMonitorException ex) { - String errorMessage = String.format(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.PrioritizeError"), manifestFilePath); + String errorMessage = String.format(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.PrioritizeError"), job.getManifest().getFilePath()); logger.log(Level.SEVERE, errorMessage, ex); MessageNotifyUtil.Message.error(errorMessage); } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboardTopComponent.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboardTopComponent.java index 24369b9da2..19a99031f8 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboardTopComponent.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboardTopComponent.java @@ -50,10 +50,6 @@ public final class AutoIngestDashboardTopComponent extends TopComponent { @Messages({ "AutoIngestDashboardTopComponent.exceptionMessage.failedToCreateDashboard=Failed to create Auto Ingest Dashboard.",}) public static void openTopComponent() { - /* - * DLG: Please make the top component initial size big enough to show - * the whole dashboard. - */ final AutoIngestDashboardTopComponent tc = (AutoIngestDashboardTopComponent) WindowManager.getDefault().findTopComponent(PREFERRED_ID); if (tc != null) { topComponentInitialized = true; @@ -67,7 +63,7 @@ public final class AutoIngestDashboardTopComponent extends TopComponent { try { dashboard = AutoIngestDashboard.createDashboard(); tc.add(dashboard); - dashboard.setSize(992, 744); + dashboard.setSize(dashboard.getPreferredSize()); if (tc.isOpened() == false) { tc.open(); } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java index d4986c82c7..74a1cb37e6 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java @@ -34,8 +34,8 @@ import org.sleuthkit.autopsy.coreutils.NetworkUtils; import org.sleuthkit.autopsy.ingest.IngestJob; /** - * An automated ingest job for a manifest. The manifest specifies a co-located - * data source and a case to which the data source is to be added. + * An automated ingest job, which is an ingest job performed by the automated + * ingest service. */ @ThreadSafe public final class AutoIngestJob implements Comparable, Serializable { @@ -44,9 +44,13 @@ public final class AutoIngestJob implements Comparable, Serializa private static final int CURRENT_VERSION = 1; private static final int DEFAULT_PRIORITY = 0; private static final String LOCAL_HOST_NAME = NetworkUtils.getLocalHostName(); - private final int version; + + /* + * Version 0 fields. + */ private final Manifest manifest; - private final String nodeName; + @GuardedBy("this") + private String nodeName; @GuardedBy("this") private String caseDirectoryPath; @GuardedBy("this") @@ -56,8 +60,6 @@ public final class AutoIngestJob implements Comparable, Serializa @GuardedBy("this") private Date stageStartDate; @GuardedBy("this") - private StageDetails stageDetails; - @GuardedBy("this") transient private DataSourceProcessor dataSourceProcessor; @GuardedBy("this") transient private IngestJob ingestJob; @@ -69,96 +71,116 @@ public final class AutoIngestJob implements Comparable, Serializa private Date completedDate; @GuardedBy("this") private boolean errorsOccurred; + + /* + * Version 1 fields. + */ + private final int version; // For possible future use. @GuardedBy("this") private ProcessingStatus processingStatus; @GuardedBy("this") private int numberOfCrashes; + @GuardedBy("this") + private StageDetails stageDetails; /** - * Constructs a new automated ingest job for a manifest. All job state not - * specified in the manifest is set to the default state for a new job. + * Constructs a new automated ingest job. All job state not specified in the + * job manifest is set to the default state for a new job. * - * @param manifest The manifest. + * @param manifest The manifest for an automated ingest job. */ AutoIngestJob(Manifest manifest) { - this.version = CURRENT_VERSION; + /* + * Version 0 fields. + */ this.manifest = manifest; - this.nodeName = AutoIngestJob.LOCAL_HOST_NAME; + this.nodeName = ""; this.caseDirectoryPath = ""; this.priority = DEFAULT_PRIORITY; this.stage = Stage.PENDING; this.stageStartDate = manifest.getDateFileCreated(); - this.stageDetails = this.getStageDetails(); this.dataSourceProcessor = null; this.ingestJob = null; this.cancelled = false; this.completed = false; this.completedDate = new Date(0); this.errorsOccurred = false; + + /* + * Version 1 fields. + */ + this.version = CURRENT_VERSION; this.processingStatus = ProcessingStatus.PENDING; this.numberOfCrashes = 0; + this.stageDetails = this.getProcessingStageDetails(); } /** - * Constructs an automated ingest job for a manifest. The manifest specifies - * a co-located data source and a case to which the data source is to be - * added. + * Constructs an automated ingest job using the coordination service node + * data for the job. * - * Note: Manifest objects will be phased out and no longer be part of the - * AutoIngestJob class. - * - * @param nodeData The node data. + * @param nodeData The coordination service node data for an automated + * ingest job. */ AutoIngestJob(AutoIngestJobNodeData nodeData) { - this.version = nodeData.getVersion(); + /* + * Version 0 fields. + */ this.manifest = new Manifest(nodeData.getManifestFilePath(), nodeData.getManifestFileDate(), nodeData.getCaseName(), nodeData.getDeviceId(), nodeData.getDataSourcePath(), Collections.emptyMap()); this.nodeName = nodeData.getProcessingHostName(); this.caseDirectoryPath = nodeData.getCaseDirectoryPath().toString(); this.priority = nodeData.getPriority(); this.stage = nodeData.getProcessingStage(); this.stageStartDate = nodeData.getProcessingStageStartDate(); - this.stageDetails = this.getStageDetails(); - this.dataSourceProcessor = null; - this.ingestJob = null; - this.cancelled = false; - this.completed = false; + this.dataSourceProcessor = null; // Transient data not in node data. + this.ingestJob = null; // Transient data not in node data. + this.cancelled = false; // Transient data not in node data. + this.completed = false; // Transient data not in node data. this.completedDate = nodeData.getCompletedDate(); this.errorsOccurred = nodeData.getErrorsOccurred(); + + /* + * Version 1 fields. + */ + this.version = CURRENT_VERSION; this.processingStatus = nodeData.getProcessingStatus(); this.numberOfCrashes = nodeData.getNumberOfCrashes(); + this.stageDetails = this.getProcessingStageDetails(); } /** - * Gets the auto ingest job manifest. + * Gets the job manifest. * - * @return The manifest. + * @return The job manifest. */ Manifest getManifest() { return this.manifest; } /** - * Sets the path to the case directory of the case associated with this job. + * Sets the path to the case directory for the job. * - * @param caseDirectoryPath The path to the case directory. + * @param caseDirectoryPath The path to the case directory. Can be the empty + * path if the case directory has not been created + * yet. */ synchronized void setCaseDirectoryPath(Path caseDirectoryPath) { - this.caseDirectoryPath = caseDirectoryPath.toString(); + if (null != caseDirectoryPath) { + this.caseDirectoryPath = caseDirectoryPath.toString(); + } else { + this.caseDirectoryPath = ""; + } } /** - * Gets the path to the case directory of the case associated with this job, - * may be null. + * Gets the path to the case directory for job, may be the empty path if the + * case directory has not been created yet. * - * @return The case directory path or null if the case directory has not - * been created yet. + * @return The case directory path. Will be the empty path if the case + * directory has not been created yet. */ synchronized Path getCaseDirectoryPath() { - if (!caseDirectoryPath.isEmpty()) { - return Paths.get(caseDirectoryPath); - } else { - return null; - } + return Paths.get(caseDirectoryPath); } /** @@ -181,7 +203,13 @@ public final class AutoIngestJob implements Comparable, Serializa return this.priority; } - synchronized void setStage(Stage newStage) { + /** + * Sets the processing stage of the job. The start date/time for the stage + * is set when the stage is set. + * + * @param newStage The processing stage. + */ + synchronized void setProcessingStage(Stage newStage) { if (Stage.CANCELLING == this.stage && Stage.COMPLETED != newStage) { return; } @@ -189,15 +217,35 @@ public final class AutoIngestJob implements Comparable, Serializa this.stageStartDate = Date.from(Instant.now()); } + /** + * Gets the processing stage of the job. + * + * @return The processing stage. + */ synchronized Stage getProcessingStage() { return this.stage; } + /** + * Gets the date/time the current processing stage of the job started. + * + * @return The current processing stage start date/time. + */ synchronized Date getProcessingStageStartDate() { return new Date(this.stageStartDate.getTime()); } - synchronized StageDetails getStageDetails() { + /** + * Gets any available details associated with the current processing stage + * of the job, e.g., the currently running data source level ingest module, + * an ingest module in the process of being cancelled, etc. If no additional + * details are available, the stage details will be the same as the + * processing stage. + * + * @return A stage details object consisting of a descrition and associated + * date/time. + */ + synchronized StageDetails getProcessingStageDetails() { String description; Date startDate; if (Stage.CANCELLING != this.stage && null != this.ingestJob) { @@ -235,24 +283,43 @@ public final class AutoIngestJob implements Comparable, Serializa return this.stageDetails; } - synchronized void setStageDetails(StageDetails stageDetails) { - this.stageDetails = stageDetails; - } - + /** + * Sets the data source processor for the job. Used for job cancellation. + * + * @param dataSourceProcessor A data source processor for the job. + */ synchronized void setDataSourceProcessor(DataSourceProcessor dataSourceProcessor) { this.dataSourceProcessor = dataSourceProcessor; } + /** + * Sets the ingest job for the auto ingest job. Used for obtaining + * processing stage details, cancelling the currently running data source + * ingest module, and cancelling the job. + * + * @param ingestJob The ingest job for the auto ingest job. + */ synchronized void setIngestJob(IngestJob ingestJob) { this.ingestJob = ingestJob; } + /** + * Gets the ingest job for the auto ingest job. + * + * @return The ingest job, may be null. + * + * TODO (JIRA-3059): Provide an AutoIngestJob ingest module cancellation API + * instead. + */ synchronized IngestJob getIngestJob() { return this.ingestJob; } + /** + * Cancels the job. + */ synchronized void cancel() { - setStage(Stage.CANCELLING); + setProcessingStage(Stage.CANCELLING); cancelled = true; errorsOccurred = true; if (null != dataSourceProcessor) { @@ -263,15 +330,33 @@ public final class AutoIngestJob implements Comparable, Serializa } } + /** + * Indicates whether or not the job has been cancelled. This is transient + * state used by the auto ingest manager that is not saved as coordination + * service node data for the job. + * + * @return True or false. + */ synchronized boolean isCanceled() { return cancelled; } + /** + * Marks the job as completed. This is transient state used by the auto + * ingest manager that is not saved as coordination service node data for + * the job. + */ synchronized void setCompleted() { - setStage(Stage.COMPLETED); + setProcessingStage(Stage.COMPLETED); completed = true; } + /** + * Indicates whether or not the job has been completed. This is transient + * state that is not saved as coordination service node data for the job. + * + * @return True or false. + */ synchronized boolean isCompleted() { return completed; } @@ -314,55 +399,108 @@ public final class AutoIngestJob implements Comparable, Serializa return this.errorsOccurred; } + /** + * Gets the processing host name for this job. + * + * @return The processing host name. + */ synchronized String getProcessingHostName() { return nodeName; } - int getVersion() { - return this.version; + /** + * Sets the processing host name for this job. + * + * @param processingHostName The processing host name. + */ + synchronized void setProcessingHostName(String processingHostName) { + this.nodeName = processingHostName; } + /** + * Gets the processing status of the job. + * + * @return The processing status. + */ synchronized ProcessingStatus getProcessingStatus() { return this.processingStatus; } + /** + * Sets the processing status of the job. + * + * @param processingStatus The processing status. + */ synchronized void setProcessingStatus(ProcessingStatus processingStatus) { this.processingStatus = processingStatus; } + /** + * Gets the number of time this job has "crashed" during processing. + * + * @return The number of crashes. + */ synchronized int getNumberOfCrashes() { return this.numberOfCrashes; } + /** + * Sets the number of time this job has "crashed" during processing. + * + * @param numberOfCrashes The number of crashes. + */ synchronized void setNumberOfCrashes(int numberOfCrashes) { this.numberOfCrashes = numberOfCrashes; } + /** + * Indicates whether some other job is "equal to" this job. Two jobs are + * equal if they have the same manifest file path. + * + * @param otherJob The job to which this job is to be compared. + * + * @return True or false. + */ @Override - public boolean equals(Object obj) { - if (!(obj instanceof AutoIngestJob)) { + public boolean equals(Object otherJob) { + if (!(otherJob instanceof AutoIngestJob)) { return false; } - if (obj == this) { + if (otherJob == this) { return true; } - return this.getManifest().getFilePath().equals(((AutoIngestJob) obj).getManifest().getFilePath()); - } - - @Override - public int hashCode() { - int hash = 71 * (Objects.hashCode(this.caseDirectoryPath)); - return hash; - } - - @Override - public int compareTo(AutoIngestJob o) { - return -this.getManifest().getDateFileCreated().compareTo(o.getManifest().getDateFileCreated()); + return this.getManifest().getFilePath().equals(((AutoIngestJob) otherJob).getManifest().getFilePath()); } /** - * Custom comparator that allows us to sort List on reverse - * chronological date modified (descending) + * Returns a hash code value for the job. The hash code is derived from the + * manifest file path. + * + * @return The hash code. + */ + @Override + public int hashCode() { + int hash = 71 * (Objects.hashCode(this.getManifest().getFilePath())); + return hash; + } + + /** + * Compares one job to another in a way that orders jobs by manifest + * creation date. + * + * @param otherJob The job to which this job is to be compared. + * + * @return A negative integer, zero, or a positive integer as this job is + * less than, equal to, or greater than the specified job. + */ + @Override + public int compareTo(AutoIngestJob otherJob) { + return -this.getManifest().getDateFileCreated().compareTo(otherJob.getManifest().getDateFileCreated()); + } + + /** + * Comparator that supports doing a descending sort of jobs based on job + * completion date. */ static class ReverseCompletedDateComparator implements Comparator { @@ -374,7 +512,8 @@ public final class AutoIngestJob implements Comparable, Serializa } /** - * Comparator that sorts auto ingest jobs by priority in descending order. + * Comparator that supports doing a descending sort of jobs based on job + * priority. */ public static class PriorityComparator implements Comparator { @@ -386,27 +525,26 @@ public final class AutoIngestJob implements Comparable, Serializa } /** - * Custom comparator that allows us to sort List on case name - * alphabetically except for jobs for the current host, which are placed at - * the top of the list. + * Comparator that supports doing an alphabetical sort of jobs based on a + * combination of case name and processing host. */ static class CaseNameAndProcessingHostComparator implements Comparator { @Override - public int compare(AutoIngestJob o1, AutoIngestJob o2) { - if (o1.getProcessingHostName().equalsIgnoreCase(LOCAL_HOST_NAME)) { - return -1; // o1 is for current case, float to top - } else if (o2.getProcessingHostName().equalsIgnoreCase(LOCAL_HOST_NAME)) { - return 1; // o2 is for current case, float to top + public int compare(AutoIngestJob aJob, AutoIngestJob anotherJob) { + if (aJob.getProcessingHostName().equalsIgnoreCase(LOCAL_HOST_NAME)) { + return -1; // aJob is for this, float to top + } else if (anotherJob.getProcessingHostName().equalsIgnoreCase(LOCAL_HOST_NAME)) { + return 1; // anotherJob is for this, float to top } else { - return o1.getManifest().getCaseName().compareToIgnoreCase(o2.getManifest().getCaseName()); + return aJob.getManifest().getCaseName().compareToIgnoreCase(anotherJob.getManifest().getCaseName()); } } } /** - * Processing status for the auto ingest job for the manifest. + * Processing statuses for an auto ingest job. */ enum ProcessingStatus { PENDING, @@ -415,6 +553,9 @@ public final class AutoIngestJob implements Comparable, Serializa DELETED } + /** + * Processing stages for an auto ingest job. + */ enum Stage { PENDING("Pending"), @@ -443,6 +584,9 @@ public final class AutoIngestJob implements Comparable, Serializa } + /** + * Processing stage details for an auto ingest job. + */ @Immutable static final class StageDetails implements Serializable { diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java index df2e321af2..3544e9ef49 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java @@ -32,8 +32,22 @@ import javax.lang.model.type.TypeKind; final class AutoIngestJobNodeData { private static final int CURRENT_VERSION = 1; - private static final int MAX_POSSIBLE_NODE_DATA_SIZE = 131629; private static final int DEFAULT_PRIORITY = 0; + + /* + * This number is the sum of each piece of data, based on it's type. For the + * types boolean, int, and long, values 1, 4, and 8 will be added + * respectively. For String objects, the length of the string, plus either a + * byte or short respesenting the length of the string, will be added. + * + * This field is used to set the size of the buffer during the byte array + * creation in the 'toArray()' method. Since the final size of the array + * isn't immediately known at the time of creation, this number is used to + * create an array as large as could possibly be needed to store all the + * data. This avoids the need to continuously enlarge the buffer. Once the + * buffer has all the necessary data, it will be resized as appropriate. + */ + private static final int MAX_POSSIBLE_NODE_DATA_SIZE = 131629; /* * Version 0 fields. @@ -48,16 +62,16 @@ final class AutoIngestJobNodeData { * Version 1 fields. */ private int version; - private String manifestFilePath; + private String manifestFilePath; // 'short' length used in byte array private long manifestFileDate; - private String caseName; - private String deviceId; - private String dataSourcePath; - private String caseDirectoryPath; - private String processingHostName; + private String caseName; // 'byte' length used in byte array + private String deviceId; // 'byte' length used in byte array + private String dataSourcePath; // 'short' length used in byte array + private String caseDirectoryPath; // 'short' length used in byte array + private String processingHostName; // 'short' length used in byte array private byte processingStage; private long processingStageStartDate; - private String processingStageDetailsDescription; + private String processingStageDetailsDescription; // 'byte' length used in byte array private long processingStageDetailsStartDate; /** @@ -84,7 +98,7 @@ final class AutoIngestJobNodeData { setProcessingHostName(job.getProcessingHostName()); setProcessingStage(job.getProcessingStage()); setProcessingStageStartDate(job.getProcessingStageStartDate()); - setProcessingStageDetails(job.getStageDetails()); + setProcessingStageDetails(job.getProcessingStageDetails()); } /** @@ -107,7 +121,7 @@ final class AutoIngestJobNodeData { this.numberOfCrashes = 0; this.completedDate = 0L; this.errorsOccurred = false; - this.version = CURRENT_VERSION; + this.version = 0; this.manifestFilePath = ""; this.manifestFileDate = 0L; this.caseName = ""; @@ -151,7 +165,7 @@ final class AutoIngestJobNodeData { this.processingStage = buffer.get(); this.processingStageStartDate = buffer.getLong(); this.processingStageDetailsDescription = getStringFromBuffer(buffer, TypeKind.BYTE); - this.processingStageDetailsStartDate = buffer.getLong();; + this.processingStageDetailsStartDate = buffer.getLong(); this.processingHostName = getStringFromBuffer(buffer, TypeKind.SHORT); } @@ -318,14 +332,14 @@ final class AutoIngestJobNodeData { /** * Gets the path to the case directory of the case associated with the job. * - * @return The case directory path or null if the case directory has not - * been created yet. + * @return The case directory path or an empty string path if the case + * directory has not been created yet. */ synchronized Path getCaseDirectoryPath() { if (!caseDirectoryPath.isEmpty()) { return Paths.get(caseDirectoryPath); } else { - return null; + return Paths.get(""); } } @@ -517,7 +531,16 @@ final class AutoIngestJobNodeData { return array; } - // DGL: Document what is going on here and how the max buffer sie constant is calculated. + /** + * This method retrieves a string from a given buffer. Depending on the type + * specified, either a 'byte' or a 'short' will first be read out of the + * buffer which gives the length of the string so it can be properly parsed. + * + * @param buffer The buffer from which the string will be read. + * @param lengthType The size of the length data. + * + * @return The string read from the buffer. + */ private String getStringFromBuffer(ByteBuffer buffer, TypeKind lengthType) { int length = 0; String output = ""; @@ -540,7 +563,16 @@ final class AutoIngestJobNodeData { return output; } - // DGL: Document what is going on here and how the max buffer sie constant is calculated. + /** + * This method puts a given string into a given buffer. Depending on the + * type specified, either a 'byte' or a 'short' will be inserted prior to + * the string which gives the length of the string so it can be properly + * parsed. + * + * @param stringValue The string to write to the buffer. + * @param buffer The buffer to which the string will be written. + * @param lengthType The size of the length data. + */ private void putStringIntoBuffer(String stringValue, ByteBuffer buffer, TypeKind lengthType) { switch (lengthType) { case BYTE: diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index c0944e9aaa..2cf88cbaa9 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -647,10 +647,10 @@ public final class AutoIngestManager extends Observable implements PropertyChang } /* - * Add the job to the pending jobs queue and update the coordinatino + * Add the job to the pending jobs queue and update the coordination * service node data for the job. */ - if (null != completedJob && null != completedJob.getCaseDirectoryPath()) { + if (null != completedJob && !completedJob.getCaseDirectoryPath().toString().isEmpty()) { try { completedJob.setErrorsOccurred(false); completedJob.setCompletedDate(new Date(0)); @@ -849,7 +849,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang if (null != ingestJob) { IngestJob.DataSourceIngestModuleHandle moduleHandle = ingestJob.getSnapshot().runningDataSourceIngestModule(); if (null != moduleHandle) { - currentJob.setStage(AutoIngestJob.Stage.CANCELLING_MODULE); + currentJob.setProcessingStage(AutoIngestJob.Stage.CANCELLING_MODULE); moduleHandle.cancel(); SYS_LOGGER.log(Level.INFO, "Cancelling {0} module for manifest {1}", new Object[]{moduleHandle.displayName(), currentJob.getManifest().getFilePath()}); } @@ -1117,7 +1117,9 @@ public final class AutoIngestManager extends Observable implements PropertyChang AutoIngestJob job = new AutoIngestJob(manifest); job.setPriority(nodeData.getPriority()); Path caseDirectory = PathUtils.findCaseDirectory(rootOutputDirectory, manifest.getCaseName()); - job.setCaseDirectoryPath(caseDirectory); + if (null != caseDirectory) { + job.setCaseDirectoryPath(caseDirectory); + } newPendingJobsList.add(job); /* @@ -1295,7 +1297,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang AutoIngestJob job = new AutoIngestJob(manifest); job.setCaseDirectoryPath(caseDirectoryPath); job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED); - job.setStage(AutoIngestJob.Stage.COMPLETED); + job.setProcessingStage(AutoIngestJob.Stage.COMPLETED); job.setCompletedDate(nodeData.getCompletedDate()); job.setErrorsOccurred(true); newCompletedJobsList.add(new AutoIngestJob(nodeData)); @@ -1864,10 +1866,11 @@ public final class AutoIngestManager extends Observable implements PropertyChang */ private void processJob() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, AutoIngestJobNodeData.InvalidDataException { Path manifestPath = currentJob.getManifest().getFilePath(); - currentJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.PROCESSING); - updateCoordinationServiceNode(currentJob); SYS_LOGGER.log(Level.INFO, "Started processing of {0}", manifestPath); - currentJob.setStage(AutoIngestJob.Stage.STARTING); + currentJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.PROCESSING); + currentJob.setProcessingStage(AutoIngestJob.Stage.STARTING); + currentJob.setProcessingHostName(AutoIngestManager.LOCAL_HOST_NAME); + updateCoordinationServiceNode(currentJob); setChanged(); notifyObservers(Event.JOB_STARTED); eventPublisher.publishRemotely(new AutoIngestJobStartedEvent(currentJob)); @@ -1890,6 +1893,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang // The job may get retried currentJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.PENDING); } + currentJob.setProcessingHostName(""); updateCoordinationServiceNode(currentJob); boolean retry = (!currentJob.isCanceled() && !currentJob.isCompleted()); @@ -1986,7 +1990,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang if (AutoIngestUserPreferences.getSharedConfigEnabled()) { Path manifestPath = currentJob.getManifest().getFilePath(); SYS_LOGGER.log(Level.INFO, "Downloading shared configuration for {0}", manifestPath); - currentJob.setStage(AutoIngestJob.Stage.UPDATING_SHARED_CONFIG); + currentJob.setProcessingStage(AutoIngestJob.Stage.UPDATING_SHARED_CONFIG); new SharedConfiguration().downloadConfiguration(); } } @@ -2004,7 +2008,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang private void verifyRequiredSevicesAreRunning() throws ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException { Path manifestPath = currentJob.getManifest().getFilePath(); SYS_LOGGER.log(Level.INFO, "Checking services availability for {0}", manifestPath); - currentJob.setStage(AutoIngestJob.Stage.CHECKING_SERVICES); + currentJob.setProcessingStage(AutoIngestJob.Stage.CHECKING_SERVICES); if (!isServiceUp(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString())) { throw new DatabaseServerDownException("Case database server is down"); } @@ -2051,7 +2055,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang Manifest manifest = currentJob.getManifest(); String caseName = manifest.getCaseName(); SYS_LOGGER.log(Level.INFO, "Opening case {0} for {1}", new Object[]{caseName, manifest.getFilePath()}); - currentJob.setStage(AutoIngestJob.Stage.OPENING_CASE); + currentJob.setProcessingStage(AutoIngestJob.Stage.OPENING_CASE); /* * Acquire and hold a case name lock so that only one node at as * time can scan the output directory at a time. This prevents @@ -2164,7 +2168,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang DataSource dataSource = identifyDataSource(caseForJob); if (null == dataSource) { - currentJob.setStage(AutoIngestJob.Stage.COMPLETED); + currentJob.setProcessingStage(AutoIngestJob.Stage.COMPLETED); return; } @@ -2174,7 +2178,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang runDataSourceProcessor(caseForJob, dataSource); if (dataSource.getContent().isEmpty()) { - currentJob.setStage(AutoIngestJob.Stage.COMPLETED); + currentJob.setProcessingStage(AutoIngestJob.Stage.COMPLETED); return; } @@ -2219,7 +2223,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang Manifest manifest = currentJob.getManifest(); Path manifestPath = manifest.getFilePath(); SYS_LOGGER.log(Level.INFO, "Identifying data source for {0} ", manifestPath); - currentJob.setStage(AutoIngestJob.Stage.IDENTIFYING_DATA_SOURCE); + currentJob.setProcessingStage(AutoIngestJob.Stage.IDENTIFYING_DATA_SOURCE); Path caseDirectoryPath = currentJob.getCaseDirectoryPath(); AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, manifest.getDataSourceFileName(), caseDirectoryPath); Path dataSourcePath = manifest.getDataSourcePath(); @@ -2255,7 +2259,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang Manifest manifest = currentJob.getManifest(); Path manifestPath = manifest.getFilePath(); SYS_LOGGER.log(Level.INFO, "Adding data source for {0} ", manifestPath); - currentJob.setStage(AutoIngestJob.Stage.ADDING_DATA_SOURCE); + currentJob.setProcessingStage(AutoIngestJob.Stage.ADDING_DATA_SOURCE); UUID taskId = UUID.randomUUID(); DataSourceProcessorCallback callBack = new AddDataSourceCallback(caseForJob, dataSource, taskId); DataSourceProcessorProgressMonitor progressMonitor = new DoNothingDSPProgressMonitor(); @@ -2420,7 +2424,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang Manifest manifest = currentJob.getManifest(); Path manifestPath = manifest.getFilePath(); SYS_LOGGER.log(Level.INFO, "Starting ingest modules analysis for {0} ", manifestPath); - currentJob.setStage(AutoIngestJob.Stage.ANALYZING_DATA_SOURCE); + currentJob.setProcessingStage(AutoIngestJob.Stage.ANALYZING_DATA_SOURCE); Path caseDirectoryPath = currentJob.getCaseDirectoryPath(); AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, manifest.getDataSourceFileName(), caseDirectoryPath); IngestJobEventListener ingestJobEventListener = new IngestJobEventListener(); @@ -2456,7 +2460,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang } jobLogger.logAnalysisCompleted(); } else { - currentJob.setStage(AutoIngestJob.Stage.CANCELLING); + currentJob.setProcessingStage(AutoIngestJob.Stage.CANCELLING); currentJob.setErrorsOccurred(true); AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log jobLogger.logAnalysisCancelled(); @@ -2519,7 +2523,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang Manifest manifest = currentJob.getManifest(); Path manifestPath = manifest.getFilePath(); SYS_LOGGER.log(Level.INFO, "Exporting files for {0}", manifestPath); - currentJob.setStage(AutoIngestJob.Stage.EXPORTING_FILES); + currentJob.setProcessingStage(AutoIngestJob.Stage.EXPORTING_FILES); Path caseDirectoryPath = currentJob.getCaseDirectoryPath(); AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, manifest.getDataSourceFileName(), caseDirectoryPath); try { @@ -2770,9 +2774,10 @@ public final class AutoIngestManager extends Observable implements PropertyChang try { synchronized (jobsLock) { if (currentJob != null) { - currentJob.getStageDetails(); + currentJob.getProcessingStageDetails(); setChanged(); notifyObservers(Event.JOB_STATUS_UPDATED); + updateCoordinationServiceNode(currentJob); eventPublisher.publishRemotely(new AutoIngestJobStatusEvent(currentJob)); } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java index 2000bba6f0..3fcc5648ba 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java @@ -19,13 +19,10 @@ package org.sleuthkit.autopsy.experimental.autoingest; import com.google.common.util.concurrent.ThreadFactoryBuilder; -import java.awt.Cursor; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Observable; @@ -34,7 +31,6 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import javax.annotation.concurrent.GuardedBy; -import org.openide.util.Exceptions; import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; import org.sleuthkit.autopsy.coreutils.Logger; @@ -143,8 +139,6 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang */ private void handleJobStartedEvent(AutoIngestJobStartedEvent event) { synchronized (jobsLock) { - // DLG: TEST! Remove job from pending queue, if present - // DLG: TEST! Add job to running jobs list jobsSnapshot.removePendingJob(event.getJob()); jobsSnapshot.addOrReplaceRunningJob(event.getJob()); setChanged(); @@ -159,8 +153,12 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang */ private void handleJobStatusEvent(AutoIngestJobStatusEvent event) { synchronized (jobsLock) { - // DLG: TEST! Replace job in running list with job from event - jobsSnapshot.addOrReplaceRunningJob(event.getJob()); + /* + * Currently this event is only published for running jobs. + */ + AutoIngestJob job = event.getJob(); + jobsSnapshot.removePendingJob(job); + jobsSnapshot.addOrReplaceRunningJob(job); setChanged(); notifyObservers(jobsSnapshot); } @@ -173,10 +171,10 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang */ private void handleJobCompletedEvent(AutoIngestJobCompletedEvent event) { synchronized (jobsLock) { - // DLG: TEST! Remove job from event from running list, if present - // DLG: TEST! Add job to completed list - jobsSnapshot.removeRunningJob(event.getJob()); - jobsSnapshot.addOrReplaceCompletedJob(event.getJob()); + AutoIngestJob job = event.getJob(); + jobsSnapshot.removePendingJob(job); + jobsSnapshot.removeRunningJob(job); + jobsSnapshot.addOrReplaceCompletedJob(job); setChanged(); notifyObservers(jobsSnapshot); } @@ -241,6 +239,13 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang for (String node : nodeList) { try { AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, node)); + if (nodeData.getVersion() < 1) { + /* + * Ignore version '0' nodes that have not been + * "upgraded" since they don't carry enough data. + */ + continue; + } AutoIngestJob job = new AutoIngestJob(nodeData); ProcessingStatus processingStatus = nodeData.getProcessingStatus(); switch (processingStatus) { @@ -275,9 +280,9 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang /** * Bumps the priority of an auto ingest job. * - * @param manifestPath The manifest file path for the job to be prioritized. + * @param job The job to be prioritized. */ - JobsSnapshot prioritizeJob(Path manifestFilePath) throws AutoIngestMonitorException { + JobsSnapshot prioritizeJob(AutoIngestJob job) throws AutoIngestMonitorException { int highestPriority = 0; AutoIngestJob prioritizedJob = null; synchronized (jobsLock) { @@ -285,11 +290,11 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang * Get the highest known priority and make sure the job is still in * the pending jobs queue. */ - for (AutoIngestJob job : jobsSnapshot.getPendingJobs()) { - if (job.getPriority() > highestPriority) { - highestPriority = job.getPriority(); + for (AutoIngestJob pendingJob : jobsSnapshot.getPendingJobs()) { + if (pendingJob.getPriority() > highestPriority) { + highestPriority = pendingJob.getPriority(); } - if (job.getManifest().getFilePath().equals(manifestFilePath)) { + if (pendingJob.equals(job)) { prioritizedJob = job; } } @@ -300,27 +305,25 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang */ if (null != prioritizedJob) { ++highestPriority; - String manifestNodePath = prioritizedJob.getManifest().getFilePath().toString(); + String manifestNodePath = job.getManifest().getFilePath().toString(); try { AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath)); nodeData.setPriority(highestPriority); coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath, nodeData.toArray()); } catch (AutoIngestJobNodeData.InvalidDataException | CoordinationServiceException | InterruptedException ex) { - throw new AutoIngestMonitorException("Error bumping priority for job " + prioritizedJob.toString(), ex); + throw new AutoIngestMonitorException("Error bumping priority for job " + job.toString(), ex); } prioritizedJob.setPriority(highestPriority); - } - /* - * Publish a prioritization event. - */ - if (null != prioritizedJob) { - final String caseName = prioritizedJob.getManifest().getCaseName(); + /* + * Publish a prioritization event. + */ + final String caseName = job.getManifest().getCaseName(); new Thread(() -> { eventPublisher.publishRemotely(new AutoIngestCasePrioritizedEvent(LOCAL_HOST_NAME, caseName)); }).start(); - } + } return jobsSnapshot; } } @@ -344,7 +347,7 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang synchronized (jobsLock) { jobsSnapshot = newJobsSnapshot; setChanged(); - notifyObservers(jobsSnapshot); + notifyObservers(null); } } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties index a22410a70e..1633373467 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties @@ -11,45 +11,16 @@ AutoIngestDashboard.JobsTableModel.ColumnHeader.CompletedTime=Job Completed AutoIngestDashboard.JobsTableModel.ColumnHeader.Stage=Stage AutoIngestDashboard.JobsTableModel.ColumnHeader.Status=Status AutoIngestDashboard.JobsTableModel.ColumnHeader.ManifestFilePath= Manifest File Path -AutoIngestDashboard.bnResume.text=Resume -AutoIngestDashboard.bnPause.confirmHeader=Are you sure you want to pause? -AutoIngestDashboard.bnPause.warningText=Pause will occur after the current job completes processing. This could take a long time. Continue? -AutoIngestDashboard.bnPause.toolTipTextResume=Resume processing of Pending Jobs -AutoIngestDashboard.bnPause.pausing=Pausing after current job completes... -AutoIngestDashboard.Cancelling=Cancelling... AutoIngestDashboard.pendingTable.toolTipText=The Pending table displays the order upcoming Jobs will be processed with the top of the list first AutoIngestDashboard.runningTable.toolTipText=The Running table displays the currently running Job and information about it AutoIngestDashboard.completedTable.toolTipText=The Completed table shows all Jobs that have been processed already AutoIngestDashboard.JobsTableModel.ColumnHeader.StageTime=Time in Stage -AutoIngestDashboard.JobsTableModel.ColumnHeader.CaseFolder=Case Folder -AutoIngestDashboard.JobsTableModel.ColumnHeader.LocalJob= Local Job? -AutoIngestDashboard.DeletionFailed=Deletion failed for job -AutoIngestDashboard.ShowLogFailed.Title=Unable to display case log -AutoIngestDashboard.ShowLogFailed.Message=Case log file does not exist -AutoIngestDashboard.bnPrioritizeCase.toolTipText=Move all images associated with a case to top of Pending queue. -AutoIngestDashboard.ExitConsequences=This will cancel any currently running job on this host. Exiting while a job is running potentially leaves the case in an inconsistent or corrupted state. -AutoIngestDashboard.ExitingStatus=Exiting... -AutoIngestDashboard.OK=OK -AutoIngestDashboard.Cancel=Cancel -AutoIngestDashboard.AutoIngestStartupFailed.Message=Failed to start automated ingest.\nPlease see auto ingest system log for details. -AutoIngestDashboard.AutoIngestStartupFailed.Title=Automated Ingest Error -AutoIngestDashboard.AutoIngestStartupError=Failed to start automated ingest. Verify Multi-user Settings. -AutoIngestDashboard.AutoIngestStartupWarning.Title=Automated Ingest Warning -AutoIngestDashboard.AutoIngestStartupWarning.Message=Failed to establish remote communications with other automated ingest nodes.\nAuto ingest dashboard will only be able to display local ingest job events.\nPlease verify Multi-User settings (Options->Multi-User). See application log for details. -AutoIngestDashboard.UpdatingSharedConfig=Updating shared configuration -AutoIngestDashboard.SharedConfigurationDisabled=Shared configuration disabled -AutoIngestDashboard.EnableConfigurationSettings=Enable shared configuration from the options panel before uploading -AutoIngestDashboard.ErrorUploadingConfiguration=Error uploading configuration -AutoIngestDashboard.UploadSuccessTitle=Success -AutoIngestDashboard.UploadSuccess=Shared configuration successfully uploaded -AutoIngestDashboard.UploadFailedTitle=Failed -AutoIngestDashboard.ConfigLocked=The shared configuration directory is locked because upload from another node is in progress. \nIf this is an error, you can unlock the directory and then retry the upload. -AutoIngestDashboard.ConfigLockedTitle=Configuration directory locked +AutoIngestDashboard.JobsTableModel.ColumnHeader.CaseFolder=Case +AutoIngestDashboard.JobsTableModel.ColumnHeader.Job=Job AutoIngestDashboard.tbServicesStatusMessage.Message=Case databases {0}, keyword search {1}, coordination {2}, messaging {3} AutoIngestDashboard.tbServicesStatusMessage.Message.Up=up AutoIngestDashboard.tbServicesStatusMessage.Message.Down=down AutoIngestDashboard.tbServicesStatusMessage.Message.Unknown=unknown -AutoIngestDashboard.PauseDueToSystemError=Paused due to system error, please consult the auto ingest system log ConfirmationDialog.DoNotDelete=Do not delete ConfirmationDialog.Delete=Permanently delete ConfirmationDialog.DeleteAreYouSure=The entire case will be removed. Are you sure you want to delete case @@ -260,7 +231,6 @@ FileExporterSettingsPanel.BrowseReportTooltip_1=Browse for the Reports Folder FileExporterSettingsPanel.NewRuleTooltip_1=Clear the rule editor to begin a new rule FileExporterSettingsPanel.DeleteTooltip_1=Delete the selected rule FileExporterSettingsPanel.SaveTooltip_1=Save the current rule -AutoIngestDashboard.bnPrioritizeFolder.label= AutoIngestCasePanel.rbDays.text=Days AutoIngestCasePanel.rbWeeks.text=Weeks AutoIngestCasePanel.rbMonths.text=Months diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Manifest.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Manifest.java index e3c4cb6bb1..5a42a01e80 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Manifest.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Manifest.java @@ -42,7 +42,7 @@ public final class Manifest implements Serializable { this.dateFileCreated = dateFileCreated; this.caseName = caseName; this.deviceId = deviceId; - if (dataSourcePath != null) { + if (null != dataSourcePath) { this.dataSourcePath = dataSourcePath.toString(); } else { this.dataSourcePath = ""; @@ -55,7 +55,7 @@ public final class Manifest implements Serializable { } public Date getDateFileCreated() { - return this.dateFileCreated; + return new Date(this.dateFileCreated.getTime()); } public String getCaseName() { diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/dashboardWsmode.xml b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/dashboardWsmode.xml index 49305ab59f..3f681aa72f 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/dashboardWsmode.xml +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/dashboardWsmode.xml @@ -3,7 +3,7 @@ - + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java index e7b633a133..ccb2e49e54 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java @@ -778,26 +778,26 @@ public class SharedConfiguration { } /** - * Upload Central Repository settings. + * Upload central repository settings. * * @param remoteFolder Shared settings folder * * @throws SharedConfigurationException */ private void uploadCentralRepositorySettings(File remoteFolder) throws SharedConfigurationException { - publishTask("Uploading Central Repository configuration"); + publishTask("Uploading central repository configuration"); copyToRemoteFolder(CENTRAL_REPOSITORY_PROPERTIES_FILE, moduleDirPath, remoteFolder, true); } /** - * Download Central Repository settings. + * Download central repository settings. * * @param remoteFolder Shared settings folder * * @throws SharedConfigurationException */ private void downloadCentralRepositorySettings(File remoteFolder) throws SharedConfigurationException { - publishTask("Downloading Central Repository configuration"); + publishTask("Downloading central repository configuration"); copyToLocalFolder(CENTRAL_REPOSITORY_PROPERTIES_FILE, moduleDirPath, remoteFolder, true); } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenHelpAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenHelpAction.java deleted file mode 100755 index 4b3be4813a..0000000000 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenHelpAction.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2013 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.imagegallery.actions; - -import java.awt.Desktop; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.IOException; -import java.net.URI; -import java.util.logging.Level; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.awt.ActionRegistration; -import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.coreutils.Logger; - -@ActionID( - category = "Help", - id = "org.sleuthkit.autopsy.imagegallery.actions.OpenHelpAction" -) -@ActionRegistration( - displayName = "#CTL_OpenHelpAction" -) -@ActionReference(path = "Menu/Help", position = 350) -@Messages("CTL_OpenHelpAction=Image / Video Gallery Help") -public final class OpenHelpAction implements ActionListener { - - @Override - public void actionPerformed(ActionEvent e) { - try { - Desktop.getDesktop().browse(URI.create("http://sleuthkit.org/autopsy/docs/user-docs/4.4.1/image_gallery_page.html")); //NON-NLS - } catch (IOException ex) { - Logger.getLogger(OpenHelpAction.class.getName()).log(Level.SEVERE, "failed to open help page", ex); //NON-NLS - } - } -} diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java index 72f9622729..2dc85cbfd9 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java @@ -136,7 +136,15 @@ public class Toolbar extends ToolBar { tagGroupMenuButton.setText(followUpGroupAction.getText()); tagGroupMenuButton.setGraphic(followUpGroupAction.getGraphic()); } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Could create follow up tag menu item", ex); //NON-NLS + /* + * The problem appears to be a timing issue where a case is closed + * before this initialization is completed, which It appears to be + * harmless, so we are temporarily changing this log message to a + * WARNING. + * + * TODO (JIRA-3010): SEVERE error logged by image Gallery UI + */ + LOGGER.log(Level.WARNING, "Could not create Follow Up tag menu item", ex); //NON-NLS } tagGroupMenuButton.showingProperty().addListener(showing -> { if (tagGroupMenuButton.isShowing()) { diff --git a/build.xml b/build.xml index 685f285fda..deda12f21e 100755 --- a/build.xml +++ b/build.xml @@ -265,7 +265,6 @@ -