Merge pull request #2906 from narfindustries/hashdb_imports

Hashdb import error handling and code cleanup - resolved merge conflicts
This commit is contained in:
Richard Cordovano 2017-06-28 15:10:12 -04:00 committed by GitHub
commit 5c456e51a3
7 changed files with 198 additions and 191 deletions

View File

@ -32,6 +32,7 @@ import java.sql.Types;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.TskData;
@ -48,10 +49,8 @@ public abstract class AbstractSqlEamDb implements EamDb {
protected final List<EamArtifact.Type> DEFAULT_ARTIFACT_TYPES;
private int bulkArtifactsCount;
private int bulkGlobalArtifactsCount;
protected int bulkArtifactsThreshold;
private final Map<String, Collection<EamArtifact>> bulkArtifacts;
private final Map<String, Collection<EamGlobalFileInstance>> bulkGlobalArtifacts;
private final List<String> badTags;
/**
@ -60,18 +59,15 @@ public abstract class AbstractSqlEamDb implements EamDb {
* @throws UnknownHostException, EamDbException
*/
protected AbstractSqlEamDb() {
badTags = new ArrayList<String>();
badTags = new ArrayList<>();
bulkArtifactsCount = 0;
bulkGlobalArtifactsCount = 0;
bulkArtifacts = new HashMap<>();
bulkGlobalArtifacts = new HashMap<>();
DEFAULT_ARTIFACT_TYPES = EamArtifact.getDefaultArtifactTypes();
for (EamArtifact.Type type : DEFAULT_ARTIFACT_TYPES) {
DEFAULT_ARTIFACT_TYPES.forEach((type) -> {
bulkArtifacts.put(type.getName(), new ArrayList<>());
bulkGlobalArtifacts.put(type.getName(), new ArrayList<>());
}
});
}
/**
@ -1449,64 +1445,32 @@ public abstract class AbstractSqlEamDb implements EamDb {
}
}
/**
* Add a new global file instance to the bulk collection
*
* @param eamGlobalFileInstance The global file instance to add
*
* @throws EamDbException
*/
@Override
public void prepareGlobalFileInstance(EamGlobalFileInstance eamGlobalFileInstance) throws EamDbException {
synchronized (bulkGlobalArtifacts) {
bulkGlobalArtifacts.get("FILES").add(eamGlobalFileInstance); // NON-NLS
bulkGlobalArtifactsCount++;
if (bulkGlobalArtifactsCount >= bulkArtifactsThreshold) {
bulkInsertGlobalFileInstances();
}
}
}
/**
* Insert the bulk collection of Global File Instances
*
* @throws EamDbException
*/
@Override
public void bulkInsertGlobalFileInstances() throws EamDbException {
List<EamArtifact.Type> artifactTypes = getCorrelationArtifactTypes();
public void bulkInsertGlobalFileInstances(Set<EamGlobalFileInstance> globalInstances, EamArtifact.Type contentType) throws EamDbException {
Connection conn = connect();
synchronized (bulkGlobalArtifacts) {
if (bulkGlobalArtifactsCount == 0) {
return;
}
PreparedStatement bulkPs = null;
try {
for (EamArtifact.Type type : artifactTypes) {
// FUTURE: have a separate global_files table for each Type.
String sql = "INSERT INTO global_files(global_reference_set_id, value, known_status, comment) VALUES (?, ?, ?, ?) "
+ getConflictClause();
bulkPs = conn.prepareStatement(sql);
Collection<EamGlobalFileInstance> eamGlobalFileInstances = bulkGlobalArtifacts.get(type.getName());
for (EamGlobalFileInstance eamGlobalFileInstance : eamGlobalFileInstances) {
bulkPs.setInt(1, eamGlobalFileInstance.getGlobalSetID());
bulkPs.setString(2, eamGlobalFileInstance.getMD5Hash());
bulkPs.setString(3, eamGlobalFileInstance.getKnownStatus().name());
bulkPs.setString(4, eamGlobalFileInstance.getComment());
for (EamGlobalFileInstance globalInstance : globalInstances) {
bulkPs.setInt(1, globalInstance.getGlobalSetID());
bulkPs.setString(2, globalInstance.getMD5Hash());
bulkPs.setString(3, globalInstance.getKnownStatus().name());
bulkPs.setString(4, globalInstance.getComment());
bulkPs.addBatch();
}
bulkPs.executeBatch();
bulkGlobalArtifacts.get(type.getName()).clear();
}
// Reset state
bulkGlobalArtifactsCount = 0;
} catch (SQLException ex) {
throw new EamDbException("Error inserting bulk artifacts.", ex); // NON-NLS
} finally {
@ -1514,7 +1478,6 @@ public abstract class AbstractSqlEamDb implements EamDb {
EamDbUtil.closeConnection(conn);
}
}
}
/**
* Get all global file instances having a given MD5 hash

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.centralrepository.datamodel;
import java.util.List;
import java.util.Set;
/**
* Main interface for interacting with the database
@ -422,14 +423,17 @@ public interface EamDb {
*
* @throws EamDbException
*/
void prepareGlobalFileInstance(EamGlobalFileInstance eamGlobalFileInstance) throws EamDbException;
// void prepareGlobalFileInstance(EamGlobalFileInstance eamGlobalFileInstance) throws EamDbException;
/**
* Insert the bulk collection of Global File Instances
*
* @param globalInstances a Set of EamGlobalFileInstances to insert into the db.
* @param contentType the Type of the global instances
*
* @throws EamDbException
*/
void bulkInsertGlobalFileInstances() throws EamDbException;
void bulkInsertGlobalFileInstances(Set<EamGlobalFileInstance> globalInstances, EamArtifact.Type contentType) throws EamDbException;
/**
* Get all global file instances having a given MD5 hash

View File

@ -43,5 +43,4 @@ public class EamDbException extends Exception {
public EamDbException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -18,9 +18,9 @@
*/
package org.sleuthkit.autopsy.centralrepository.datamodel;
import java.util.Objects;
import org.sleuthkit.datamodel.TskData;
/**
* Global file hash instance
*/
@ -53,6 +53,25 @@ public class EamGlobalFileInstance {
this(-1, globalSetID, MD5Hash, knownStatus, comment);
}
@Override
public boolean equals(Object otherInstance) {
if (this == otherInstance) {
return true;
} else if (!(otherInstance instanceof EamGlobalFileInstance)) {
return false;
} else {
return (this.hashCode() == otherInstance.hashCode());
}
}
@Override
public int hashCode() {
int hash = 5;
hash = 59 * hash + this.globalSetID;
hash = 59 * hash + Objects.hashCode(this.MD5Hash);
hash = 59 * hash + this.knownStatus.hashCode();
return hash;
}
/**
* @return the instanceID
*/

View File

@ -2,13 +2,6 @@ OptionsCategory_Name_Central_Repository_Options=Central Repository
OptionsCategory_Keywords_Central_Repository_Options=Central Repository Settings
ImportHashDatabaseDialog.known.text=Known
ImportHashDatabaseDialog.knownBad.text=Known Bad
ImportHashDatabaseDialog.importHashDbMsg=Import Hash Database
ImportHashDatabaseDialog.fileNameExtFilter.text=Hash Database File
ImportHashDatabaseDialog.failedToGetDbPathMsg=Failed to get the path of the selected database.
ImportHashDatabaseDialog.importHashDbErr=Import Hash Database Error
ImportHashDatabaseDialog.mustSelectHashDbFilePathMsg=A hash database file path must be selected.
ImportHashDatabaseDialog.hashDbDoesNotExistMsg=The selected hash database does not exist.
ImportHashDatabaseDialog.errorMessage.failedToOpenHashDbMsg=Failed to open hash database at {0}.
EamPostgresSettingsDialog.lbUserPassword.text=User Password :
EamPostgresSettingsDialog.lbUserName.text=User Name :
EamPostgresSettingsDialog.bnCancel.text=Cancel

View File

@ -27,13 +27,12 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="lbInstructions" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="lbWarningMsg" max="32767" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="okButton" linkSize="1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="cancelButton" linkSize="1" min="-2" max="-2" attributes="0"/>
@ -87,6 +86,7 @@
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Component id="lbWarningMsg" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
@ -96,13 +96,15 @@
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="lbInstructions" max="32767" attributes="0"/>
<Component id="lbInstructions" min="-2" pref="26" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="openButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="tfFilePath" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="lbDatabasePath" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="lbDatabaseType" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
@ -130,15 +132,19 @@
<Component id="lbDatabaseVersion" alignment="3" min="-2" pref="20" max="-2" attributes="0"/>
<Component id="tfDatabaseVersion" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="lbWarningMsg" min="-2" pref="23" max="-2" attributes="0"/>
<EmptySpace pref="44" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="32767" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="okButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="lbWarningMsg" min="-2" pref="23" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>

View File

@ -29,22 +29,28 @@ import java.nio.file.Files;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.spi.options.OptionsPanelController;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifact;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactInstance;
@ -53,6 +59,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.EamGlobalFileInstance;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamGlobalSet;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.datamodel.TskData;
/**
@ -76,9 +83,10 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
* and add it to the set of hash databases used to classify files as
* unknown, known, or known bad.
*/
@Messages({"ImportHashDatabaseDialog.importHashDbMsg=Import Hash Database"})
ImportHashDatabaseDialog() {
super((JFrame) WindowManager.getDefault().getMainWindow(),
NbBundle.getMessage(ImportHashDatabaseDialog.class, "ImportHashDatabaseDialog.importHashDbMsg"),
Bundle.ImportHashDatabaseDialog_importHashDbMsg(),
true); // NON-NLS
textBoxes = new ArrayList<>();
textBoxChangedListener = new TextBoxChangedListener();
@ -88,12 +96,14 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
display();
}
@Messages({"ImportHashDatabaseDialog.fileNameExtFilter.text=Hash Database File",})
private void initFileChooser() {
fileChooser.setDragEnabled(false);
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
String[] EXTENSION = new String[]{"idx"}; //NON-NLS
FileNameExtensionFilter filter = new FileNameExtensionFilter(
NbBundle.getMessage(this.getClass(), "ImportHashDatabaseDialog.fileNameExtFilter.text"), EXTENSION); // NON-NLS
Bundle.ImportHashDatabaseDialog_fileNameExtFilter_text(),
EXTENSION); // NON-NLS
fileChooser.setFileFilter(filter);
fileChooser.setMultiSelectionEnabled(false);
}
@ -108,6 +118,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
* Register for notifications when the text boxes get updated.
*/
private void setTextBoxListeners() {
textBoxes.add(tfFilePath);
textBoxes.add(tfDatabaseName);
textBoxes.add(tfDatabaseVersion);
addDocumentListeners(textBoxes, textBoxChangedListener);
@ -339,8 +350,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lbInstructions, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(lbWarningMsg, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGap(18, 18, 18)
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(okButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cancelButton))
@ -379,7 +389,8 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
.addComponent(knownRadioButton)
.addComponent(knownBadRadioButton)))
.addComponent(lbDatabaseAttribution))
.addGap(0, 0, Short.MAX_VALUE)))
.addGap(0, 0, Short.MAX_VALUE))
.addComponent(lbWarningMsg, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
@ -389,12 +400,14 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(lbInstructions, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lbInstructions, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(openButton)
.addComponent(tfFilePath, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lbDatabasePath))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lbDatabaseType)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
@ -418,18 +431,21 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lbDatabaseVersion, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(tfDatabaseVersion, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lbWarningMsg, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(44, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(okButton)
.addComponent(cancelButton))
.addComponent(lbWarningMsg, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
.addContainerGap())))
);
pack();
}// </editor-fold>//GEN-END:initComponents
@Messages({"ImportHashDatabaseDialog.failedToGetDbPathMsg=Failed to get the path of the selected database.",})
private void openButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openButtonActionPerformed
if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
File databaseFile = fileChooser.getSelectedFile();
@ -441,9 +457,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
ModuleSettings.setConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY, databaseFile.getParent());
} catch (IOException ex) {
Logger.getLogger(ImportHashDatabaseDialog.class.getName()).log(Level.SEVERE, "Failed to get path of selected database", ex); // NON-NLS
JOptionPane.showMessageDialog(this,
NbBundle.getMessage(this.getClass(),
"ImportHashDatabaseDialog.failedToGetDbPathMsg")); // NON-NLS
lbWarningMsg.setText(Bundle.ImportHashDatabaseDialog_failedToGetDbPathMsg());
}
}
valid();
@ -470,7 +484,11 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
}
@Messages({"ImportHashDatabaseDialog.createGlobalSet.failedMsg.text=Failed to store attribution details.",
"ImportHashDatabaseDialog.createGlobalSet.failedTitle.text=Import hashdb error."})
"ImportHashDatabaseDialog.mustSelectHashDbFilePathMsg=Missing hash database file path.",
"ImportHashDatabaseDialog.hashDbDoesNotExistMsg=The selected hash database does not exist.",
"# {0} - selected file path",
"ImportHashDatabaseDialog.errorMessage.failedToOpenHashDbMsg=Failed to open hash database at {0}.",
})
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
// Note that the error handlers in this method call return without disposing of the
// dialog to allow the user to try again, if desired.
@ -478,34 +496,22 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
// have valid file path
if (selectedFilePath.isEmpty()) {
JOptionPane.showMessageDialog(this,
NbBundle.getMessage(this.getClass(),
"ImportHashDatabaseDialog.mustSelectHashDbFilePathMsg"),
NbBundle.getMessage(this.getClass(),
"ImportHashDatabaseDialog.importHashDbErr"),
JOptionPane.ERROR_MESSAGE); // NON-NLS
lbWarningMsg.setText(Bundle.ImportHashDatabaseDialog_mustSelectHashDbFilePathMsg());
return;
}
File file = new File(selectedFilePath);
if (!file.exists()) {
JOptionPane.showMessageDialog(this,
NbBundle.getMessage(this.getClass(),
"ImportHashDatabaseDialog.hashDbDoesNotExistMsg"),
NbBundle.getMessage(this.getClass(),
"ImportHashDatabaseDialog.importHashDbErr"),
JOptionPane.ERROR_MESSAGE); // NON-NLS
lbWarningMsg.setText(Bundle.ImportHashDatabaseDialog_hashDbDoesNotExistMsg());
return;
}
// create global set
int globalSetID = -1;
int globalSetID;
try {
globalSetID = createGlobalSet();
} catch (EamDbException ex) {
JOptionPane.showMessageDialog(this,
Bundle.ImportHashDatabaseDialog_createGlobalSet_failedMsg_text(),
Bundle.ImportHashDatabaseDialog_createGlobalSet_failedTitle_text(),
JOptionPane.ERROR_MESSAGE);
LOGGER.log(Level.SEVERE, "Failed to create global set.", ex);
lbWarningMsg.setText(Bundle.ImportHashDatabaseDialog_createGlobalSet_failedMsg_text());
return;
}
@ -517,22 +523,18 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
knownStatus = TskData.FileKnown.BAD;
}
String errorMessage = NbBundle.getMessage(this.getClass(),
"ImportHashDatabaseDialog.errorMessage.failedToOpenHashDbMsg",
selectedFilePath); // NON-NLS
String errorMessage = Bundle.ImportHashDatabaseDialog_errorMessage_failedToOpenHashDbMsg(selectedFilePath);
// Future, make UI handle more than the "FILES" type.
EamArtifact.Type contentType = EamArtifact.getDefaultArtifactTypes().get(0); // get "FILES" type
try {
new ImportHashDatabaseWorker(selectedFilePath, knownStatus, globalSetID).execute();
} catch (Throwable ex) {
Logger.getLogger(ImportHashDatabaseDialog.class.getName()).log(Level.WARNING, errorMessage, ex);
JOptionPane.showMessageDialog(this,
ex.getMessage(),
NbBundle.getMessage(this.getClass(),
"ImportHashDatabaseDialog.importHashDbErr"),
JOptionPane.ERROR_MESSAGE);
return;
// run in the background and close dialog
SwingUtilities.invokeLater(new ImportHashDatabaseWorker(selectedFilePath, knownStatus, globalSetID, contentType)::execute);
dispose();
} catch (EamDbException | UnknownHostException ex) {
Logger.getLogger(ImportHashDatabaseDialog.class.getName()).log(Level.SEVERE, errorMessage, ex);
lbWarningMsg.setText(ex.getMessage());
}
dispose();
}//GEN-LAST:event_okButtonActionPerformed
@SuppressWarnings({"unchecked"})
@ -560,37 +562,57 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
}//GEN-LAST:event_comboboxSourceOrganizationActionPerformed
@NbBundle.Messages({"ImportHashDatabaseDialog.ImportHashDatabaseWorker.displayName=Importing Hash Database"})
private class ImportHashDatabaseWorker extends SwingWorker<Object, Void> {
private class ImportHashDatabaseWorker extends SwingWorker<Void, Void> {
private final File file;
private final TskData.FileKnown knownStatus;
private final int globalSetID;
private final ProgressHandle progress;
private final EamArtifact.Type contentType;
public ImportHashDatabaseWorker(String filename, TskData.FileKnown knownStatus, int globalSetID) throws EamDbException, UnknownHostException {
public ImportHashDatabaseWorker(String filename, TskData.FileKnown knownStatus, int globalSetID, EamArtifact.Type contentType) throws EamDbException, UnknownHostException {
this.file = new File(filename);
this.knownStatus = knownStatus;
this.globalSetID = globalSetID;
this.contentType = contentType;
this.progress = ProgressHandle.createHandle(Bundle.ImportHashDatabaseDialog_ImportHashDatabaseWorker_displayName());
if (!EamDb.isEnabled()) {
throw new EamDbException("Central Repository database settings were not properly initialized"); // NON-NLS
throw new EamDbException("Central Repository database is not enabled."); // NON-NLS
}
}
@Override
protected Object doInBackground() throws Exception {
ProgressHandle progress = ProgressHandle.createHandle(Bundle.ImportHashDatabaseDialog_ImportHashDatabaseWorker_displayName());
importHashDatabase(progress);
protected Void doInBackground() throws Exception {
importHashDatabase();
return null;
}
@Override
@Messages({"ImportHashDatabaseDialog.ImportHashDatabaseWorker.error=Failed to import hash database."})
protected void done() {
progress.finish();
try {
get();
} catch (InterruptedException | ExecutionException ex) {
Logger.getLogger(ImportHashDatabaseDialog.class.getName()).log(Level.SEVERE, Bundle.ImportHashDatabaseDialog_ImportHashDatabaseWorker_error(), ex);
MessageNotifyUtil.Notify.show(Bundle.ImportHashDatabaseDialog_ImportHashDatabaseWorker_error(),
ex.getMessage(),
MessageNotifyUtil.MessageType.ERROR);
}
}
private long numberOfLinesInFile(File f) throws IOException {
return Files.lines(f.toPath()).count();
}
private void importHashDatabase(ProgressHandle progress) throws EamDbException, IOException {
@Messages({"# {0} - value content",
"ImportHashDatabaseDialog.ImportHashDatabaseWorker.duplicate=Duplicate value {0} found in import file."})
private void importHashDatabase() throws EamDbException, IOException {
BufferedReader reader = new BufferedReader(new FileReader(file));
String line;
EamDb dbManager = EamDb.getInstance();
Set<EamGlobalFileInstance> globalInstances = new HashSet<>();
long totalLines = numberOfLinesInFile(file);
if (totalLines <= Integer.MAX_VALUE) {
@ -616,11 +638,12 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
knownStatus,
"");
dbManager.prepareGlobalFileInstance(eamGlobalFileInstance);
if (!globalInstances.add(eamGlobalFileInstance)) {
throw new EamDbException(Bundle.ImportHashDatabaseDialog_ImportHashDatabaseWorker_duplicate(parts[0])); // NON-NLS
}
}
dbManager.bulkInsertGlobalFileInstances();
progress.finish();
dbManager.bulkInsertGlobalFileInstances(globalInstances, contentType);
}
}