Autopsy  4.14.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
ImportCentralRepoDbProgressDialog.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2018 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.modules.hashdatabase;
20 
21 import java.awt.Color;
22 import java.beans.PropertyChangeListener;
23 import java.beans.PropertyChangeEvent;
24 import java.util.HashSet;
25 import java.util.Set;
26 import java.util.logging.Level;
27 import javax.swing.JFrame;
28 import javax.swing.SwingWorker;
29 import javax.swing.WindowConstants;
30 import java.util.concurrent.atomic.AtomicLong;
31 import java.util.concurrent.atomic.AtomicBoolean;
32 import java.util.concurrent.atomic.AtomicInteger;
33 import java.util.concurrent.Executors;
34 import org.openide.util.NbBundle;
35 import org.openide.windows.WindowManager;
41 import org.sleuthkit.datamodel.TskCoreException;
42 import org.sleuthkit.datamodel.TskData;
44 
48 @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
49 class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements PropertyChangeListener {
50 
51  private static final long serialVersionUID = 1L;
52 
53  private CentralRepoImportWorker worker; // Swing worker that will import the file and send updates to the dialog
54 
55  @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.title.text=Central Repository Import Progress",})
56  ImportCentralRepoDbProgressDialog() {
57  super((JFrame) WindowManager.getDefault().getMainWindow(),
58  Bundle.ImportCentralRepoDbProgressDialog_title_text(),
59  true);
60 
61  initComponents();
62  customizeComponents();
63  }
64 
65  private void customizeComponents() {
66  // This is preventing the user from closing the dialog using the X
67  setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
68 
69  bnOk.setEnabled(false);
70  }
71 
85  void importFile(String hashSetName, String version, int orgId,
86  boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType,
87  boolean readOnly, String importFileName) {
88 
89  worker = new CentralRepoImportWorker(hashSetName, version, orgId, searchDuringIngest, sendIngestMessages,
90  knownFilesType, readOnly, importFileName);
91  worker.addPropertyChangeListener(this);
92  worker.execute();
93 
94  setLocationRelativeTo((JFrame) WindowManager.getDefault().getMainWindow());
95  this.setVisible(true);
96  }
97 
104  HashDbManager.HashDb getDatabase() {
105  if (worker != null) {
106  return worker.getDatabase();
107  }
108  return null;
109  }
110 
117  @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.errorParsingFile.message=Error parsing hash set file"})
118  @Override
119  public void propertyChange(PropertyChangeEvent evt) {
120 
121  if ("progress".equals(evt.getPropertyName())) {
122  // The progress has been updated. Update the progress bar and text
123  progressBar.setValue(worker.getProgress());
124  lbProgress.setText(getProgressString());
125  } else if ("state".equals(evt.getPropertyName())
126  && (SwingWorker.StateValue.DONE.equals(evt.getNewValue()))) {
127 
128  // The worker is done processing
129  // Disable cancel button and enable ok
130  bnCancel.setEnabled(false);
131  bnOk.setEnabled(true);
132 
133  if (worker.getImportSuccess()) {
134  // If the import succeeded, finish the progress bar and display the
135  // total number of imported hashes
136  progressBar.setValue(progressBar.getMaximum());
137  lbProgress.setText(getProgressString());
138  } else {
139  // If there was an error, reset the progress bar and display an error message
140  progressBar.setValue(0);
141  lbProgress.setForeground(Color.red);
142  lbProgress.setText(Bundle.ImportCentralRepoDbProgressDialog_errorParsingFile_message());
143  }
144  }
145  }
146 
147  @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.linesProcessed.message= hashes processed"})
148  private String getProgressString() {
149  return worker.getNumHashesProcessed() + Bundle.ImportCentralRepoDbProgressDialog_linesProcessed_message();
150  }
151 
152  private class CentralRepoImportWorker extends SwingWorker<Void, Void> {
153 
154  private final int HASH_IMPORT_THRESHOLD = 10000;
155  private final String hashSetName;
156  private final String version;
157  private final int orgId;
158  private final boolean searchDuringIngest;
159  private final boolean sendIngestMessages;
161  private final boolean readOnly;
162  private final String importFileName;
163  private HashDbManager.CentralRepoHashSet newHashDb = null;
164  private final AtomicInteger referenceSetID = new AtomicInteger();
165  private final AtomicLong hashCount = new AtomicLong();
166  private final AtomicBoolean importSuccess = new AtomicBoolean();
167 
168  CentralRepoImportWorker(String hashSetName, String version, int orgId,
169  boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType,
170  boolean readOnly, String importFileName) {
171 
172  this.hashSetName = hashSetName;
173  this.version = version;
174  this.orgId = orgId;
175  this.searchDuringIngest = searchDuringIngest;
176  this.sendIngestMessages = sendIngestMessages;
177  this.knownFilesType = knownFilesType;
178  this.readOnly = readOnly;
179  this.importFileName = importFileName;
180  this.hashCount.set(0);
181  this.importSuccess.set(false);
182  this.referenceSetID.set(-1);
183  }
184 
191  synchronized HashDbManager.CentralRepoHashSet getDatabase() {
192  return newHashDb;
193  }
194 
200  long getNumHashesProcessed() {
201  return hashCount.get();
202  }
203 
210  boolean getImportSuccess() {
211  return importSuccess.get();
212  }
213 
214  @Override
215  protected Void doInBackground() throws Exception {
216 
217  // Create the hash set parser
218  HashSetParser hashSetParser;
219  if (importFileName.toLowerCase().endsWith(".idx") || importFileName.toLowerCase().endsWith(".txt")) {
220  hashSetParser = new IdxHashSetParser(importFileName);
221  } else if (importFileName.toLowerCase().endsWith(".hash")) {
222  hashSetParser = new EncaseHashSetParser(importFileName);
223  } else if (importFileName.toLowerCase().endsWith(".kdb")) {
224  hashSetParser = new KdbHashSetParser(importFileName);
225  } else if (importFileName.toLowerCase().endsWith(".hsh")) {
226  hashSetParser = new HashkeeperHashSetParser(importFileName);
227  } else {
228  // We've gotten here with a format that can't be processed
229  throw new TskCoreException("Hash set to import is an unknown format : " + importFileName);
230  }
231 
232  try {
233  // Conver to the FileKnown enum used by EamGlobalSet
234  TskData.FileKnown knownStatus;
235  if (knownFilesType.equals(HashDbManager.HashDb.KnownFilesType.KNOWN)) {
236  knownStatus = TskData.FileKnown.KNOWN;
237  } else {
238  knownStatus = TskData.FileKnown.BAD;
239  }
240 
241  // Create an empty hashset in the central repository
243  referenceSetID.set(dbManager.newReferenceSet(new CentralRepoFileSet(orgId, hashSetName, version, knownStatus,
245 
246  // Get the "FILES" content type. This is a database lookup so we
247  // only want to do it once.
249 
250  // Holds the current batch of hashes that need to be written to the central repo
251  Set<CentralRepoFileInstance> globalInstances = new HashSet<>();
252 
253  while (!hashSetParser.doneReading()) {
254  if (isCancelled()) {
255  return null;
256  }
257 
258  String newHash = hashSetParser.getNextHash();
259 
260  if (newHash != null) {
261  CentralRepoFileInstance eamGlobalFileInstance = new CentralRepoFileInstance(
262  referenceSetID.get(),
263  newHash,
264  knownStatus,
265  "");
266 
267  globalInstances.add(eamGlobalFileInstance);
268 
269  // If we've hit the threshold for writing the hashes, write them
270  // all to the central repo
271  if (hashCount.incrementAndGet() % HASH_IMPORT_THRESHOLD == 0) {
272  dbManager.bulkInsertReferenceTypeEntries(globalInstances, contentType);
273  globalInstances.clear();
274 
275  int progress = (int) (hashCount.get() * 100 / hashSetParser.getExpectedHashCount());
276  if (progress < 100) {
277  this.setProgress(progress);
278  } else {
279  this.setProgress(99);
280  }
281  }
282  }
283  }
284 
285  // Add any remaining hashes to the central repo
286  dbManager.bulkInsertReferenceTypeEntries(globalInstances, contentType);
287  this.setProgress(100);
288  return null;
289  } finally {
290  hashSetParser.close();
291  }
292  }
293 
294  private void deleteIncompleteSet() {
295  if (referenceSetID.get() >= 0) {
296 
297  // This can be slow on large reference sets
298  Executors.newSingleThreadExecutor().execute(new Runnable() {
299  @Override
300  public void run() {
301  try {
302  CentralRepository.getInstance().deleteReferenceSet(referenceSetID.get());
303  } catch (CentralRepoException ex2) {
304  Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error deleting incomplete hash set from central repository", ex2);
305  }
306  }
307  });
308  }
309  }
310 
311  @Override
312  synchronized protected void done() {
313 
314  if (isCancelled()) {
315  // If the user hit cancel, delete this incomplete hash set from the central repo
316  deleteIncompleteSet();
317  return;
318  }
319 
320  try {
321  get();
322  try {
323  newHashDb = HashDbManager.getInstance().addExistingCentralRepoHashSet(hashSetName, version,
324  referenceSetID.get(),
325  searchDuringIngest, sendIngestMessages, knownFilesType, readOnly);
326  importSuccess.set(true);
327  } catch (TskCoreException ex) {
328  Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error adding imported hash set", ex);
329  }
330  } catch (Exception ex) {
331  // Delete this incomplete hash set from the central repo
332  deleteIncompleteSet();
333  Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error importing hash set", ex);
334  }
335  }
336 
337  }
338 
344  @SuppressWarnings("unchecked")
345  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
346  private void initComponents() {
347 
348  progressBar = new javax.swing.JProgressBar();
349  lbProgress = new javax.swing.JLabel();
350  bnOk = new javax.swing.JButton();
351  bnCancel = new javax.swing.JButton();
352  jLabel1 = new javax.swing.JLabel();
353 
354  setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
355 
356  org.openide.awt.Mnemonics.setLocalizedText(lbProgress, org.openide.util.NbBundle.getMessage(ImportCentralRepoDbProgressDialog.class, "ImportCentralRepoDbProgressDialog.lbProgress.text")); // NOI18N
357 
358  org.openide.awt.Mnemonics.setLocalizedText(bnOk, org.openide.util.NbBundle.getMessage(ImportCentralRepoDbProgressDialog.class, "ImportCentralRepoDbProgressDialog.bnOk.text")); // NOI18N
359  bnOk.addActionListener(new java.awt.event.ActionListener() {
360  public void actionPerformed(java.awt.event.ActionEvent evt) {
361  bnOkActionPerformed(evt);
362  }
363  });
364 
365  org.openide.awt.Mnemonics.setLocalizedText(bnCancel, org.openide.util.NbBundle.getMessage(ImportCentralRepoDbProgressDialog.class, "ImportCentralRepoDbProgressDialog.bnCancel.text")); // NOI18N
366  bnCancel.addActionListener(new java.awt.event.ActionListener() {
367  public void actionPerformed(java.awt.event.ActionEvent evt) {
368  bnCancelActionPerformed(evt);
369  }
370  });
371 
372  org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(ImportCentralRepoDbProgressDialog.class, "ImportCentralRepoDbProgressDialog.jLabel1.text")); // NOI18N
373 
374  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
375  getContentPane().setLayout(layout);
376  layout.setHorizontalGroup(
377  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
378  .addGroup(layout.createSequentialGroup()
379  .addContainerGap()
380  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
381  .addGroup(layout.createSequentialGroup()
382  .addComponent(progressBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
383  .addContainerGap())
384  .addGroup(layout.createSequentialGroup()
385  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
386  .addComponent(jLabel1)
387  .addComponent(lbProgress))
388  .addGap(0, 0, Short.MAX_VALUE))))
389  .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
390  .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
391  .addComponent(bnOk)
392  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
393  .addComponent(bnCancel)
394  .addContainerGap())
395  );
396  layout.setVerticalGroup(
397  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
398  .addGroup(layout.createSequentialGroup()
399  .addContainerGap()
400  .addComponent(jLabel1)
401  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
402  .addComponent(lbProgress)
403  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
404  .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
405  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
406  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
407  .addComponent(bnCancel)
408  .addComponent(bnOk))
409  .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
410  );
411 
412  pack();
413  }// </editor-fold>//GEN-END:initComponents
414 
415  private void bnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnCancelActionPerformed
416  this.worker.cancel(true);
417  this.dispose();
418  }//GEN-LAST:event_bnCancelActionPerformed
419 
420  private void bnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOkActionPerformed
421  this.dispose();
422  }//GEN-LAST:event_bnOkActionPerformed
423 
424 
425  // Variables declaration - do not modify//GEN-BEGIN:variables
426  private javax.swing.JButton bnCancel;
427  private javax.swing.JButton bnOk;
428  private javax.swing.JLabel jLabel1;
429  private javax.swing.JLabel lbProgress;
430  private javax.swing.JProgressBar progressBar;
431  // End of variables declaration//GEN-END:variables
432 }
void bulkInsertReferenceTypeEntries(Set< CentralRepoFileInstance > globalInstances, CorrelationAttributeInstance.Type contentType)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
CorrelationAttributeInstance.Type getCorrelationTypeById(int typeId)

Copyright © 2012-2020 Basis Technology. Generated on: Wed Apr 8 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.