Merge pull request #5783 from gdicristofaro/5545-znodesConfirm

5545 znodes confirm
This commit is contained in:
Richard Cordovano 2020-04-15 16:07:41 -04:00 committed by GitHub
commit 16934e64a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 498 additions and 69 deletions

View File

@ -257,3 +257,8 @@ CasesDashboardTopComponent.refreshButton.text=Refresh
AutoIngestCasesDeletionDialog.jLabel1.text=Progress
CasesDashboardTopComponent.deleteOrphanCaseNodesButton.text=Delete Orphan Case Znodes
CasesDashboardTopComponent.deleteOrphanManifestNodesButton.text=Delete Orphan Manifest Znodes
DeleteOrphanCaseNodesDialog.descriptionText.text=The following cases have orphaned znodes. Would you like to delete them?
DeleteOrphanCaseNodesDialog.okButton.text=OK
DeleteOrphanCaseNodesDialog.cancelButton.text=Cancel
DeleteOrphanCaseNodesDialog.titleText.text=Delete The Following Znodes?
DeleteOrphanCaseNodesDialog.lblNodeCount.text=

View File

@ -89,10 +89,6 @@ AutoIngestControlPanel.runningTable.toolTipText=The Running table displays the c
AutoIngestControlPanel.SharedConfigurationDisabled=Shared configuration disabled
AutoIngestControlPanel.ShowLogFailed.Message=Case log file does not exist
AutoIngestControlPanel.ShowLogFailed.Title=Unable to display case log
# {0} - case db status
# {1} - search svc Status
# {2} - coord svc Status
# {3} - msg broker status
AutoIngestControlPanel.tbServicesStatusMessage.Message=Case databases {0}, keyword search {1}, coordination {2}, messaging {3}
AutoIngestControlPanel.tbServicesStatusMessage.Message.Down=down
AutoIngestControlPanel.tbServicesStatusMessage.Message.Unknown=unknown
@ -186,25 +182,23 @@ DeleteCaseTask.progress.acquiringManifestLocks=Acquiring exclusive manifest file
DeleteCaseTask.progress.connectingToCoordSvc=Connecting to the coordination service...
DeleteCaseTask.progress.deletingCaseDirCoordSvcNode=Deleting case directory znode...
DeleteCaseTask.progress.deletingCaseNameCoordSvcNode=Deleting case name znode...
# {0} - data source path
DeleteCaseTask.progress.deletingDataSource=Deleting data source {0}...
DeleteCaseTask.progress.deletingJobLogLockNode=Deleting case auto ingest log znode...
# {0} - manifest file path
DeleteCaseTask.progress.deletingManifest=Deleting manifest file {0}...
# {0} - manifest file path
DeleteCaseTask.progress.deletingManifestFileNode=Deleting the manifest file znode for {0}...
DeleteCaseTask.progress.deletingResourcesLockNode=Deleting case resources znode...
DeleteCaseTask.progress.gettingManifestPaths=Getting manifest file paths...
# {0} - manifest file path
DeleteCaseTask.progress.lockingManifest=Locking manifest file {0}...
DeleteCaseTask.progress.openingCaseDatabase=Opening the case database...
DeleteCaseTask.progress.openingCaseMetadataFile=Opening case metadata file...
# {0} - manifest file path
DeleteCaseTask.progress.parsingManifest=Parsing manifest file {0}...
# {0} - manifest file path
DeleteCaseTask.progress.releasingManifestLock=Releasing lock on the manifest file {0}...
DeleteCaseTask.progress.startMessage=Starting deletion...
DeleteOrphanCaseNodesAction.progressDisplayName=Cleanup Case Znodes
# {0} - item count
DeleteOrphanCaseNodesDialog.additionalInit.lblNodeCount.text=Znodes found: {0}
# {0} - item count
DeleteOrphanCaseNodesDialog.additionalInit.znodesTextArea.countMessage=ZNODES FOUND: {0}
DeleteOrphanCaseNodesTask.progress.connectingToCoordSvc=Connecting to the coordination service
# {0} - node path
DeleteOrphanCaseNodesTask.progress.deletingOrphanedCaseNode=Deleting orphaned case znode {0}
@ -213,7 +207,6 @@ DeleteOrphanCaseNodesTask.progress.lookingForOrphanedCaseZnodes=Looking for orph
DeleteOrphanCaseNodesTask.progress.startMessage=Starting orphaned case znode cleanup
DeleteOrphanManifestNodesAction.progressDisplayName=Cleanup Manifest File Znodes
DeleteOrphanManifestNodesTask.progress.connectingToCoordSvc=Connecting to the coordination service
# {0} - node path
DeleteOrphanManifestNodesTask.progress.deletingOrphanedManifestNode=Deleting orphaned manifest file znode {0}
DeleteOrphanManifestNodesTask.progress.gettingManifestNodes=Querying the coordination service for manifest file znodes
DeleteOrphanManifestNodesTask.progress.lookingForOrphanedManifestFileZnodes=Looking for orphaned manifest file znodes
@ -222,7 +215,6 @@ HINT_CasesDashboardTopComponent=This is an adminstrative dashboard for multi-use
OpenAutoIngestLogAction.deletedLogErrorMsg=The case auto ingest log has been deleted.
OpenAutoIngestLogAction.logOpenFailedErrorMsg=Failed to open case auto ingest log. See application log for details.
OpenAutoIngestLogAction.menuItemText=Open Auto Ingest Log File
# {0} - caseErrorMessage
OpenCaseAction.errorMsg=Failed to open case: {0}
OpenCaseAction.menuItemText=Open
OpenIDE-Module-Long-Description=This module contains features that are being developed by Basis Technology and are not part of the default Autopsy distribution. You can enable this module to use the new features. The features should be stable, but their exact behavior and API are subject to change.\n\nWe make no guarantee that the API of this module will not change, so developers should be careful when relying on it.
@ -456,3 +448,8 @@ CasesDashboardTopComponent.refreshButton.text=Refresh
AutoIngestCasesDeletionDialog.jLabel1.text=Progress
CasesDashboardTopComponent.deleteOrphanCaseNodesButton.text=Delete Orphan Case Znodes
CasesDashboardTopComponent.deleteOrphanManifestNodesButton.text=Delete Orphan Manifest Znodes
DeleteOrphanCaseNodesDialog.descriptionText.text=The following cases have orphaned znodes. Would you like to delete them?
DeleteOrphanCaseNodesDialog.okButton.text=OK
DeleteOrphanCaseNodesDialog.cancelButton.text=Cancel
DeleteOrphanCaseNodesDialog.titleText.text=Delete The Following Znodes?
DeleteOrphanCaseNodesDialog.lblNodeCount.text=

View File

@ -0,0 +1,135 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="2"/>
<Property name="title" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="DeleteOrphanCaseNodesDialog.titleText.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[535, 226]"/>
</Property>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane" alignment="1" max="32767" attributes="0"/>
<Component id="descriptionText" alignment="1" max="32767" attributes="0"/>
<Group type="102" alignment="1" attributes="0">
<Component id="lblNodeCount" min="-2" pref="310" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="okButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="cancelButton" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="descriptionText" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="jScrollPane" pref="252" max="32767" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="okButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="lblNodeCount" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="descriptionText">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="DeleteOrphanCaseNodesDialog.descriptionText.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="verticalAlignment" type="int" value="1"/>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
</Component>
<Container class="javax.swing.JScrollPane" name="jScrollPane">
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextArea" name="znodesTextArea">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="columns" type="int" value="20"/>
<Property name="lineWrap" type="boolean" value="true"/>
<Property name="rows" type="int" value="5"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="cancelButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="DeleteOrphanCaseNodesDialog.cancelButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelButtonActionPerformed"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
</Component>
<Component class="javax.swing.JButton" name="okButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="DeleteOrphanCaseNodesDialog.okButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="okButtonActionPerformed"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
</Component>
<Component class="javax.swing.JLabel" name="lblNodeCount">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="DeleteOrphanCaseNodesDialog.lblNodeCount.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,181 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.experimental.autoingest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import javax.swing.JFrame;
import org.openide.windows.WindowManager;
import org.openide.util.NbBundle.Messages;
/**
* This dialog shows the system administrator the orphaned znodes to be deleted.
* If 'OK' is selected, isOkSelected() will return true.
*/
class DeleteOrphanCaseNodesDialog extends javax.swing.JDialog {
private static final long serialVersionUID = 1L;
private static final String NEW_LINE = System.getProperty("line.separator");
private boolean okSelected = false;
/**
* Creates new form DeleteOrphanCaseNodesDialog
*
* @param zNodeCases The list of cases with nodes to be deleted
*/
DeleteOrphanCaseNodesDialog(Collection<String> zNodeCases) {
super((JFrame) WindowManager.getDefault().getMainWindow(), null, true);
initComponents();
additionalInit(zNodeCases);
}
/**
* displays this dialog as child of main window.
*/
void display() {
this.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
setVisible(true);
}
@Messages({
"# {0} - item count",
"DeleteOrphanCaseNodesDialog.additionalInit.lblNodeCount.text=Znodes found: {0}",
"# {0} - item count",
"DeleteOrphanCaseNodesDialog.additionalInit.znodesTextArea.countMessage=ZNODES FOUND: {0}"
})
private void additionalInit(Collection<String> zNodeCases) {
List<String> casesList = (zNodeCases == null) ? new ArrayList<>() : new ArrayList<>(zNodeCases);
int count = casesList.size();
casesList.sort(Comparator.comparing(String::toString));
String textAreaText = Bundle.DeleteOrphanCaseNodesDialog_additionalInit_znodesTextArea_countMessage(count)
+ NEW_LINE
+ NEW_LINE
+ String.join(NEW_LINE, casesList);
znodesTextArea.setText(textAreaText);
lblNodeCount.setText(Bundle.DeleteOrphanCaseNodesDialog_additionalInit_lblNodeCount_text(count));
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
javax.swing.JLabel descriptionText = new javax.swing.JLabel();
javax.swing.JScrollPane jScrollPane = new javax.swing.JScrollPane();
znodesTextArea = new javax.swing.JTextArea();
javax.swing.JButton cancelButton = new javax.swing.JButton();
javax.swing.JButton okButton = new javax.swing.JButton();
lblNodeCount = new javax.swing.JLabel();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setTitle(org.openide.util.NbBundle.getMessage(DeleteOrphanCaseNodesDialog.class, "DeleteOrphanCaseNodesDialog.titleText.text")); // NOI18N
setMinimumSize(new java.awt.Dimension(535, 226));
org.openide.awt.Mnemonics.setLocalizedText(descriptionText, org.openide.util.NbBundle.getMessage(DeleteOrphanCaseNodesDialog.class, "DeleteOrphanCaseNodesDialog.descriptionText.text")); // NOI18N
descriptionText.setVerticalAlignment(javax.swing.SwingConstants.TOP);
znodesTextArea.setEditable(false);
znodesTextArea.setColumns(20);
znodesTextArea.setLineWrap(true);
znodesTextArea.setRows(5);
jScrollPane.setViewportView(znodesTextArea);
org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(DeleteOrphanCaseNodesDialog.class, "DeleteOrphanCaseNodesDialog.cancelButton.text")); // NOI18N
cancelButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cancelButtonActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(okButton, org.openide.util.NbBundle.getMessage(DeleteOrphanCaseNodesDialog.class, "DeleteOrphanCaseNodesDialog.okButton.text")); // NOI18N
okButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
okButtonActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(lblNodeCount, org.openide.util.NbBundle.getMessage(DeleteOrphanCaseNodesDialog.class, "DeleteOrphanCaseNodesDialog.lblNodeCount.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(descriptionText, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(lblNodeCount, javax.swing.GroupLayout.PREFERRED_SIZE, 310, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(okButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cancelButton)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(descriptionText)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 252, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(cancelButton)
.addComponent(okButton)
.addComponent(lblNodeCount))
.addContainerGap())
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
okSelected = true;
dispose();
}//GEN-LAST:event_okButtonActionPerformed
private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
dispose();
}//GEN-LAST:event_cancelButtonActionPerformed
/**
* If the system administrator selected OK.
*
* @return Whether or not 'OK' was selected by the system administrator.
*/
boolean isOkSelected() {
return okSelected;
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel lblNodeCount;
private javax.swing.JTextArea znodesTextArea;
// End of variables declaration//GEN-END:variables
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019-2019 Basis Technology Corp.
* Copyright 2019-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -19,10 +19,17 @@
package org.sleuthkit.autopsy.experimental.autoingest;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import javax.swing.SwingUtilities;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.multiusercases.CoordinationServiceUtils;
import static org.sleuthkit.autopsy.casemodule.multiusercases.CoordinationServiceUtils.isCaseAutoIngestLogNodePath;
@ -40,8 +47,8 @@ final class DeleteOrphanCaseNodesTask implements Runnable {
private static final Logger logger = AutoIngestDashboardLogger.getLogger();
private final ProgressIndicator progress;
private int nodesCount;
private int casesCount;
private int nodesCount = 0;
private int casesCount = 0;
/**
* Constucts an instance of a task for deleting case coordination service
@ -53,6 +60,130 @@ final class DeleteOrphanCaseNodesTask implements Runnable {
this.progress = progress;
}
/**
* Retrieves an instance of the coordination service in order to fetch
* znodes and potentially delete.
*
* @return The coordination service or null on error.
*/
private CoordinationService getCoordinationService() {
progress.progress(Bundle.DeleteOrphanCaseNodesTask_progress_connectingToCoordSvc());
logger.log(Level.INFO, Bundle.DeleteOrphanCaseNodesTask_progress_connectingToCoordSvc());
CoordinationService coordinationService = null;
try {
coordinationService = CoordinationService.getInstance();
} catch (CoordinationService.CoordinationServiceException ex) {
logger.log(Level.SEVERE, "Error connecting to the coordination service", ex); //NON-NLS
}
return coordinationService;
}
/**
* Retrieves node paths for cases.
*
* @param coordinationService The coordination service to use in order to
* fetch the node paths.
*
* @return The list of node paths for cases.
*/
private List<String> getNodePaths(CoordinationService coordinationService) {
progress.progress(Bundle.DeleteOrphanCaseNodesTask_progress_gettingCaseZnodes());
logger.log(Level.INFO, Bundle.DeleteOrphanCaseNodesTask_progress_gettingCaseZnodes());
List<String> nodePaths = null;
try {
nodePaths = coordinationService.getNodeList(CoordinationService.CategoryNode.CASES);
// in the event that getNodeList returns null (but still successful) return empty list
if (nodePaths == null) {
return new ArrayList<String>();
}
} catch (CoordinationService.CoordinationServiceException ex) {
logger.log(Level.SEVERE, "Error getting case znode list", ex); //NON-NLS
} catch (InterruptedException unused) {
logger.log(Level.WARNING, "Task cancelled while getting case znode list"); //NON-NLS
}
return nodePaths;
}
private void addIfExists(List<String> paths, String path) {
if (path != null && !path.isEmpty()) {
paths.add(path);
}
}
/**
* Determines orphaned znode paths.
*
* @param nodePaths The list of case node paths.
*
* @return The list of orphaned node paths.
*/
private Map<String, List<String>> getOrphanedNodes(List<String> nodePaths) {
progress.progress(Bundle.DeleteOrphanCaseNodesTask_progress_lookingForOrphanedCaseZnodes());
logger.log(Level.INFO, Bundle.DeleteOrphanCaseNodesTask_progress_lookingForOrphanedCaseZnodes());
Map<String, List<String>> nodePathsToDelete = new HashMap<>();
for (String caseNodePath : nodePaths) {
if (isCaseNameNodePath(caseNodePath) || isCaseResourcesNodePath(caseNodePath) || isCaseAutoIngestLogNodePath(caseNodePath)) {
continue;
}
final Path caseDirectoryPath = Paths.get(caseNodePath);
final File caseDirectory = caseDirectoryPath.toFile();
if (!caseDirectory.exists()) {
String caseName = CoordinationServiceUtils.getCaseNameNodePath(caseDirectoryPath);
List<String> paths = new ArrayList<>();
addIfExists(paths, CoordinationServiceUtils.getCaseNameNodePath(caseDirectoryPath));
addIfExists(paths, CoordinationServiceUtils.getCaseResourcesNodePath(caseDirectoryPath));
addIfExists(paths, CoordinationServiceUtils.getCaseAutoIngestLogNodePath(caseDirectoryPath));
addIfExists(paths, CoordinationServiceUtils.getCaseDirectoryNodePath(caseDirectoryPath));
nodePathsToDelete.put(caseName, paths);
}
}
return nodePathsToDelete;
}
/**
* Boxed boolean so that promptUser method can set a value on a final object
* from custom jdialog message.
*/
private class PromptResult {
private boolean value = false;
boolean isValue() {
return value;
}
void setValue(boolean value) {
this.value = value;
}
}
/**
* prompts the user with a list of orphaned znodes.
*
* @param orphanedNodes The orphaned znode cases.
*
* @return True if the user would like to proceed deleting the znodes.
*/
private boolean promptUser(Collection<String> orphanedNodes) {
final PromptResult dialogResult = new PromptResult();
try {
SwingUtilities.invokeAndWait(() -> {
DeleteOrphanCaseNodesDialog dialog = new DeleteOrphanCaseNodesDialog(orphanedNodes);
dialog.display();
dialogResult.setValue(dialog.isOkSelected());
});
return dialogResult.isValue();
} catch (InterruptedException | InvocationTargetException e) {
logger.log(Level.WARNING, "Task cancelled while confirming case znodes to delete"); //NON-NLS
return false;
}
}
@Override
@NbBundle.Messages({
"DeleteOrphanCaseNodesTask.progress.startMessage=Starting orphaned case znode cleanup",
@ -63,67 +194,21 @@ final class DeleteOrphanCaseNodesTask implements Runnable {
public void run() {
progress.start(Bundle.DeleteOrphanCaseNodesTask_progress_startMessage());
try {
progress.progress(Bundle.DeleteOrphanCaseNodesTask_progress_connectingToCoordSvc());
logger.log(Level.INFO, Bundle.DeleteOrphanCaseNodesTask_progress_connectingToCoordSvc());
CoordinationService coordinationService;
try {
coordinationService = CoordinationService.getInstance();
} catch (CoordinationService.CoordinationServiceException ex) {
logger.log(Level.SEVERE, "Error connecting to the coordination service", ex); //NON-NLS
CoordinationService coordinationService = getCoordinationService();
if (coordinationService == null) {
return;
}
progress.progress(Bundle.DeleteOrphanCaseNodesTask_progress_gettingCaseZnodes());
logger.log(Level.INFO, Bundle.DeleteOrphanCaseNodesTask_progress_gettingCaseZnodes());
List<String> nodePaths;
try {
nodePaths = coordinationService.getNodeList(CoordinationService.CategoryNode.CASES);
} catch (CoordinationService.CoordinationServiceException ex) {
logger.log(Level.SEVERE, "Error getting case znode list", ex); //NON-NLS
return;
} catch (InterruptedException unused) {
logger.log(Level.WARNING, "Task cancelled while getting case znode list"); //NON-NLS
List<String> nodePaths = getNodePaths(coordinationService);
if (nodePaths == null) {
return;
}
progress.progress(Bundle.DeleteOrphanCaseNodesTask_progress_lookingForOrphanedCaseZnodes());
logger.log(Level.INFO, Bundle.DeleteOrphanCaseNodesTask_progress_lookingForOrphanedCaseZnodes());
for (String caseNodePath : nodePaths) {
if (isCaseNameNodePath(caseNodePath) || isCaseResourcesNodePath(caseNodePath) || isCaseAutoIngestLogNodePath(caseNodePath)) {
continue;
}
Map<String, List<String>> orphanedNodes = getOrphanedNodes(nodePaths);
boolean continueDelete = promptUser(orphanedNodes.keySet());
final Path caseDirectoryPath = Paths.get(caseNodePath);
final File caseDirectory = caseDirectoryPath.toFile();
if (!caseDirectory.exists()) {
String caseName = CoordinationServiceUtils.getCaseNameNodePath(caseDirectoryPath);
String nodePath = ""; // NON-NLS
try {
nodePath = CoordinationServiceUtils.getCaseNameNodePath(caseDirectoryPath);
deleteNode(coordinationService, caseName, nodePath);
nodePath = CoordinationServiceUtils.getCaseResourcesNodePath(caseDirectoryPath);
deleteNode(coordinationService, caseName, nodePath);
nodePath = CoordinationServiceUtils.getCaseAutoIngestLogNodePath(caseDirectoryPath);
deleteNode(coordinationService, caseName, nodePath);
nodePath = CoordinationServiceUtils.getCaseDirectoryNodePath(caseDirectoryPath);
deleteNode(coordinationService, caseName, nodePath);
++casesCount;
/*
* Back to looking for orphans...
*/
progress.progress(Bundle.DeleteOrphanCaseNodesTask_progress_lookingForOrphanedCaseZnodes());
logger.log(Level.INFO, Bundle.DeleteOrphanCaseNodesTask_progress_lookingForOrphanedCaseZnodes());
} catch (InterruptedException unused) {
logger.log(Level.WARNING, String.format("Task cancelled while deleting orphaned znode %s for %s", nodePath, caseName)); //NON-NLS
return;
}
}
if (continueDelete) {
deleteNodes(coordinationService, orphanedNodes);
}
} catch (Exception ex) {
@ -142,6 +227,32 @@ final class DeleteOrphanCaseNodesTask implements Runnable {
}
}
/**
* Deletes the orphaned znodes provided in the 'orphanedNodes' variable.
*
* @param coordinationService The coordination service to use for deletion.
* @param orphanedNodes A mapping of case to the orphaned znodes.
*
* @throws InterruptedException If the thread executing this task is
* interrupted during the delete operation.
*/
private void deleteNodes(CoordinationService coordinationService, Map<String, List<String>> orphanedNodes) {
String caseName = null;
String nodePath = null;
try {
for (Entry<String, List<String>> caseNodePaths : orphanedNodes.entrySet()) {
caseName = caseNodePaths.getKey();
for (String path : caseNodePaths.getValue()) {
nodePath = path;
deleteNode(coordinationService, caseName, nodePath);
}
++casesCount;
}
} catch (InterruptedException unused) {
logger.log(Level.WARNING, String.format("Task cancelled while deleting orphaned znode %s for %s", nodePath, caseName)); //NON-NLS
}
}
/**
* Attempts to delete a case coordination service node.
*