Autopsy  4.7.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;
42 import org.sleuthkit.datamodel.TskCoreException;
43 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 CentralRepoImportWorker worker; // Swing worker that will import the file and send updates to the dialog
52 
53  @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.title.text=Central Repository Import Progress",})
54  ImportCentralRepoDbProgressDialog() {
55  super((JFrame) WindowManager.getDefault().getMainWindow(),
56  Bundle.ImportCentralRepoDbProgressDialog_title_text(),
57  true);
58 
59  initComponents();
60  customizeComponents();
61  }
62 
63  private void customizeComponents() {
64  // This is preventing the user from closing the dialog using the X
65  setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
66 
67  bnOk.setEnabled(false);
68  }
69 
83  void importFile(String hashSetName, String version, int orgId,
84  boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType,
85  boolean readOnly, String importFileName) {
86 
87  worker = new CentralRepoImportWorker(hashSetName, version, orgId, searchDuringIngest, sendIngestMessages,
88  knownFilesType, readOnly, importFileName);
89  worker.addPropertyChangeListener(this);
90  worker.execute();
91 
92  setLocationRelativeTo((JFrame) WindowManager.getDefault().getMainWindow());
93  this.setVisible(true);
94  }
95 
102  HashDbManager.HashDb getDatabase() {
103  if (worker != null) {
104  return worker.getDatabase();
105  }
106  return null;
107  }
108 
115  @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.errorParsingFile.message=Error parsing hash set file"})
116  @Override
117  public void propertyChange(PropertyChangeEvent evt) {
118 
119  if ("progress".equals(evt.getPropertyName())) {
120  // The progress has been updated. Update the progress bar and text
121  progressBar.setValue(worker.getProgress());
122  lbProgress.setText(getProgressString());
123  } else if ("state".equals(evt.getPropertyName())
124  && (SwingWorker.StateValue.DONE.equals(evt.getNewValue()))) {
125 
126  // The worker is done processing
127  // Disable cancel button and enable ok
128  bnCancel.setEnabled(false);
129  bnOk.setEnabled(true);
130 
131  if (worker.getImportSuccess()) {
132  // If the import succeeded, finish the progress bar and display the
133  // total number of imported hashes
134  progressBar.setValue(progressBar.getMaximum());
135  lbProgress.setText(getProgressString());
136  } else {
137  // If there was an error, reset the progress bar and display an error message
138  progressBar.setValue(0);
139  lbProgress.setForeground(Color.red);
140  lbProgress.setText(Bundle.ImportCentralRepoDbProgressDialog_errorParsingFile_message());
141  }
142  }
143  }
144 
145  @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.linesProcessed.message= hashes processed"})
146  private String getProgressString() {
147  return worker.getNumHashesProcessed() + Bundle.ImportCentralRepoDbProgressDialog_linesProcessed_message();
148  }
149 
150  private class CentralRepoImportWorker extends SwingWorker<Void, Void> {
151 
152  private final int HASH_IMPORT_THRESHOLD = 10000;
153  private final String hashSetName;
154  private final String version;
155  private final int orgId;
156  private final boolean searchDuringIngest;
157  private final boolean sendIngestMessages;
159  private final boolean readOnly;
160  private final String importFileName;
161  private HashDbManager.CentralRepoHashSet newHashDb = null;
162  private final AtomicInteger referenceSetID = new AtomicInteger();
163  private final AtomicLong hashCount = new AtomicLong();
164  private final AtomicBoolean importSuccess = new AtomicBoolean();
165 
166  CentralRepoImportWorker(String hashSetName, String version, int orgId,
167  boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType,
168  boolean readOnly, String importFileName) {
169 
170  this.hashSetName = hashSetName;
171  this.version = version;
172  this.orgId = orgId;
173  this.searchDuringIngest = searchDuringIngest;
174  this.sendIngestMessages = sendIngestMessages;
175  this.knownFilesType = knownFilesType;
176  this.readOnly = readOnly;
177  this.importFileName = importFileName;
178  this.hashCount.set(0);
179  this.importSuccess.set(false);
180  this.referenceSetID.set(-1);
181  }
182 
189  synchronized HashDbManager.CentralRepoHashSet getDatabase() {
190  return newHashDb;
191  }
192 
198  long getNumHashesProcessed() {
199  return hashCount.get();
200  }
201 
208  boolean getImportSuccess() {
209  return importSuccess.get();
210  }
211 
212  @Override
213  protected Void doInBackground() throws Exception {
214 
215  // Create the hash set parser
216  HashSetParser hashSetParser;
217  if (importFileName.toLowerCase().endsWith(".idx") || importFileName.toLowerCase().endsWith(".txt")) {
218  hashSetParser = new IdxHashSetParser(importFileName);
219  } else if (importFileName.toLowerCase().endsWith(".hash")) {
220  hashSetParser = new EncaseHashSetParser(importFileName);
221  } else if (importFileName.toLowerCase().endsWith(".kdb")) {
222  hashSetParser = new KdbHashSetParser(importFileName);
223  } else if (importFileName.toLowerCase().endsWith(".hsh")) {
224  hashSetParser = new HashkeeperHashSetParser(importFileName);
225  } else {
226  // We've gotten here with a format that can't be processed
227  throw new TskCoreException("Hash set to import is an unknown format : " + importFileName);
228  }
229 
230  try {
231  // Conver to the FileKnown enum used by EamGlobalSet
232  TskData.FileKnown knownStatus;
233  if (knownFilesType.equals(HashDbManager.HashDb.KnownFilesType.KNOWN)) {
234  knownStatus = TskData.FileKnown.KNOWN;
235  } else {
236  knownStatus = TskData.FileKnown.BAD;
237  }
238 
239  // Create an empty hashset in the central repository
240  EamDb dbManager = EamDb.getInstance();
241  referenceSetID.set(dbManager.newReferenceSet(new EamGlobalSet(orgId, hashSetName, version, knownStatus,
243 
244  // Get the "FILES" content type. This is a database lookup so we
245  // only want to do it once.
247 
248  // Holds the current batch of hashes that need to be written to the central repo
249  Set<EamGlobalFileInstance> globalInstances = new HashSet<>();
250 
251  while (!hashSetParser.doneReading()) {
252  if (isCancelled()) {
253  return null;
254  }
255 
256  String newHash = hashSetParser.getNextHash();
257 
258  if (newHash != null) {
259  EamGlobalFileInstance eamGlobalFileInstance = new EamGlobalFileInstance(
260  referenceSetID.get(),
261  newHash,
262  knownStatus,
263  "");
264 
265  globalInstances.add(eamGlobalFileInstance);
266 
267  // If we've hit the threshold for writing the hashes, write them
268  // all to the central repo
269  if (hashCount.incrementAndGet() % HASH_IMPORT_THRESHOLD == 0) {
270  dbManager.bulkInsertReferenceTypeEntries(globalInstances, contentType);
271  globalInstances.clear();
272 
273  int progress = (int) (hashCount.get() * 100 / hashSetParser.getExpectedHashCount());
274  if (progress < 100) {
275  this.setProgress(progress);
276  } else {
277  this.setProgress(99);
278  }
279  }
280  }
281  }
282 
283  // Add any remaining hashes to the central repo
284  dbManager.bulkInsertReferenceTypeEntries(globalInstances, contentType);
285  this.setProgress(100);
286  return null;
287  } finally {
288  hashSetParser.close();
289  }
290  }
291 
292  private void deleteIncompleteSet() {
293  if (referenceSetID.get() >= 0) {
294 
295  // This can be slow on large reference sets
296  Executors.newSingleThreadExecutor().execute(new Runnable() {
297  @Override
298  public void run() {
299  try {
300  EamDb.getInstance().deleteReferenceSet(referenceSetID.get());
301  } catch (EamDbException ex2) {
302  Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error deleting incomplete hash set from central repository", ex2);
303  }
304  }
305  });
306  }
307  }
308 
309  @Override
310  synchronized protected void done() {
311 
312  if (isCancelled()) {
313  // If the user hit cancel, delete this incomplete hash set from the central repo
314  deleteIncompleteSet();
315  return;
316  }
317 
318  try {
319  get();
320  try {
321  newHashDb = HashDbManager.getInstance().addExistingCentralRepoHashSet(hashSetName, version,
322  referenceSetID.get(),
323  searchDuringIngest, sendIngestMessages, knownFilesType, readOnly);
324  importSuccess.set(true);
325  } catch (TskCoreException ex) {
326  Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error adding imported hash set", ex);
327  }
328  } catch (Exception ex) {
329  // Delete this incomplete hash set from the central repo
330  deleteIncompleteSet();
331  Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error importing hash set", ex);
332  }
333  }
334 
335  }
336 
342  @SuppressWarnings("unchecked")
343  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
344  private void initComponents() {
345 
346  progressBar = new javax.swing.JProgressBar();
347  lbProgress = new javax.swing.JLabel();
348  bnOk = new javax.swing.JButton();
349  bnCancel = new javax.swing.JButton();
350  jLabel1 = new javax.swing.JLabel();
351 
352  setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
353 
354  org.openide.awt.Mnemonics.setLocalizedText(lbProgress, org.openide.util.NbBundle.getMessage(ImportCentralRepoDbProgressDialog.class, "ImportCentralRepoDbProgressDialog.lbProgress.text")); // NOI18N
355 
356  org.openide.awt.Mnemonics.setLocalizedText(bnOk, org.openide.util.NbBundle.getMessage(ImportCentralRepoDbProgressDialog.class, "ImportCentralRepoDbProgressDialog.bnOk.text")); // NOI18N
357  bnOk.addActionListener(new java.awt.event.ActionListener() {
358  public void actionPerformed(java.awt.event.ActionEvent evt) {
359  bnOkActionPerformed(evt);
360  }
361  });
362 
363  org.openide.awt.Mnemonics.setLocalizedText(bnCancel, org.openide.util.NbBundle.getMessage(ImportCentralRepoDbProgressDialog.class, "ImportCentralRepoDbProgressDialog.bnCancel.text")); // NOI18N
364  bnCancel.addActionListener(new java.awt.event.ActionListener() {
365  public void actionPerformed(java.awt.event.ActionEvent evt) {
366  bnCancelActionPerformed(evt);
367  }
368  });
369 
370  org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(ImportCentralRepoDbProgressDialog.class, "ImportCentralRepoDbProgressDialog.jLabel1.text")); // NOI18N
371 
372  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
373  getContentPane().setLayout(layout);
374  layout.setHorizontalGroup(
375  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
376  .addGroup(layout.createSequentialGroup()
377  .addContainerGap()
378  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
379  .addGroup(layout.createSequentialGroup()
380  .addComponent(progressBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
381  .addContainerGap())
382  .addGroup(layout.createSequentialGroup()
383  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
384  .addComponent(jLabel1)
385  .addComponent(lbProgress))
386  .addGap(0, 0, Short.MAX_VALUE))))
387  .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
388  .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
389  .addComponent(bnOk)
390  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
391  .addComponent(bnCancel)
392  .addContainerGap())
393  );
394  layout.setVerticalGroup(
395  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
396  .addGroup(layout.createSequentialGroup()
397  .addContainerGap()
398  .addComponent(jLabel1)
399  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
400  .addComponent(lbProgress)
401  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
402  .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
403  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
404  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
405  .addComponent(bnCancel)
406  .addComponent(bnOk))
407  .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
408  );
409 
410  pack();
411  }// </editor-fold>//GEN-END:initComponents
412 
413  private void bnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnCancelActionPerformed
414  this.worker.cancel(true);
415  this.dispose();
416  }//GEN-LAST:event_bnCancelActionPerformed
417 
418  private void bnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOkActionPerformed
419  this.dispose();
420  }//GEN-LAST:event_bnOkActionPerformed
421 
422 
423  // Variables declaration - do not modify//GEN-BEGIN:variables
424  private javax.swing.JButton bnCancel;
425  private javax.swing.JButton bnOk;
426  private javax.swing.JLabel jLabel1;
427  private javax.swing.JLabel lbProgress;
428  private javax.swing.JProgressBar progressBar;
429  // End of variables declaration//GEN-END:variables
430 }
CorrelationAttribute.Type getCorrelationTypeById(int typeId)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
void bulkInsertReferenceTypeEntries(Set< EamGlobalFileInstance > globalInstances, CorrelationAttribute.Type contentType)

Copyright © 2012-2016 Basis Technology. Generated on: Mon Jun 18 2018
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.