Autopsy  4.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
AddImageWizardIngestConfigPanel.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2015 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.casemodule;
20 
21 import org.openide.util.NbBundle;
22 import java.awt.Color;
23 import java.awt.Component;
24 import java.awt.Window;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.UUID;
29 import javax.swing.JButton;
30 import javax.swing.JOptionPane;
31 import javax.swing.SwingUtilities;
32 import javax.swing.event.ChangeListener;
33 import org.openide.WizardDescriptor;
34 import org.openide.util.HelpCtx;
35 import org.sleuthkit.datamodel.Content;
42 
49 class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDescriptor> {
50 
51  private final IngestJobSettingsPanel ingestJobSettingsPanel;
52 
57  private Component component = null;
58 
59  private final List<Content> newContents = Collections.synchronizedList(new ArrayList<Content>());
60  private boolean ingested = false;
61  private boolean readyToIngest = false;
62 
63  // task that will clean up the created database file if the wizard is cancelled before it finishes
64  private AddImageAction.CleanupTask cleanupTask;
65 
66  private final AddImageAction addImageAction;
67 
68  private final AddImageWizardAddingProgressPanel progressPanel;
69  private final AddImageWizardChooseDataSourcePanel dataSourcePanel;
70 
71  private DataSourceProcessor dsProcessor;
72  private boolean cancelled;
73 
74  AddImageWizardIngestConfigPanel(AddImageWizardChooseDataSourcePanel dsPanel, AddImageAction action, AddImageWizardAddingProgressPanel proPanel) {
75  this.addImageAction = action;
76  this.progressPanel = proPanel;
77  this.dataSourcePanel = dsPanel;
78 
79  IngestJobSettings ingestJobSettings = new IngestJobSettings(AddImageWizardIngestConfigPanel.class.getCanonicalName());
80  showWarnings(ingestJobSettings);
81  this.ingestJobSettingsPanel = new IngestJobSettingsPanel(ingestJobSettings);
82  }
83 
92  @Override
93  public Component getComponent() {
94  if (component == null) {
95  component = new AddImageWizardIngestConfigVisual(this.ingestJobSettingsPanel);
96  }
97  return component;
98  }
99 
106  @Override
107  public HelpCtx getHelp() {
108  // Show no Help button for this panel:
109  return HelpCtx.DEFAULT_HELP;
110  // If you have context help:
111  // return new HelpCtx(SampleWizardPanel1.class);
112  }
113 
120  @Override
121  public boolean isValid() {
122  // If it is always OK to press Next or Finish, then:
123  return true;
124  // If it depends on some condition (form filled out...), then:
125  // return someCondition();
126  // and when this condition changes (last form field filled in...) then:
127  // fireChangeEvent();
128  // and uncomment the complicated stuff below.
129  }
130 
136  @Override
137  public final void addChangeListener(ChangeListener l) {
138  }
139 
145  @Override
146  public final void removeChangeListener(ChangeListener l) {
147  }
148 
149  // You can use a settings object to keep track of state. Normally the
150  // settings object will be the WizardDescriptor, so you can use
151  // WizardDescriptor.getProperty & putProperty to store information entered
152  // by the user.
161  @Override
162  public void readSettings(WizardDescriptor settings) {
163  JButton cancel = new JButton(
164  NbBundle.getMessage(this.getClass(), "AddImageWizardIngestConfigPanel.CANCEL_BUTTON.text"));
165  cancel.setEnabled(false);
166  settings.setOptions(new Object[]{WizardDescriptor.PREVIOUS_OPTION, WizardDescriptor.NEXT_OPTION, WizardDescriptor.FINISH_OPTION, cancel});
167  cleanupTask = null;
168  readyToIngest = false;
169 
170  newContents.clear();
171 
172  // Start processing the data source by handing it off to the selected DSP,
173  // so it gets going in the background while the user is still picking the Ingest modules
174  startDataSourceProcessing(settings);
175  }
176 
186  @Override
187  public void storeSettings(WizardDescriptor settings) {
188  IngestJobSettings ingestJobSettings = this.ingestJobSettingsPanel.getSettings();
189  ingestJobSettings.save();
190  showWarnings(ingestJobSettings);
191 
192  // Start ingest if it hasn't already been started
193  readyToIngest = true;
194  startIngest();
195  }
196 
197  private static void showWarnings(IngestJobSettings ingestJobSettings) {
198  List<String> warnings = ingestJobSettings.getWarnings();
199  if (warnings.isEmpty() == false) {
200  StringBuilder warningMessage = new StringBuilder();
201  for (String warning : warnings) {
202  warningMessage.append(warning).append("\n");
203  }
204  JOptionPane.showMessageDialog(null, warningMessage.toString());
205  }
206  }
207 
212  private void startIngest() {
213  if (!newContents.isEmpty() && readyToIngest && !ingested) {
214  ingested = true;
215  IngestManager.getInstance().queueIngestJob(newContents, ingestJobSettingsPanel.getSettings());
216  progressPanel.setStateFinished();
217  }
218  }
219 
224  private void startDataSourceProcessing(WizardDescriptor settings) {
225  final UUID dataSourceId = UUID.randomUUID();
226 
227  // Add a cleanup task to interrupt the background process if the
228  // wizard exits while the background process is running.
229  cleanupTask = addImageAction.new CleanupTask() {
230  @Override
231  void cleanup() throws Exception {
232  cancelDataSourceProcessing(dataSourceId);
233  cancelled = true;
234  }
235  };
236 
237  cleanupTask.enable();
238 
239  // get the selected DSProcessor
240  dsProcessor = dataSourcePanel.getComponent().getCurrentDSProcessor();
241 
242  new Thread(() -> {
243  Case.getCurrentCase().notifyAddingDataSource(dataSourceId);
244  }).start();
245  DataSourceProcessorCallback cbObj = new DataSourceProcessorCallback() {
246  @Override
247  public void doneEDT(DataSourceProcessorCallback.DataSourceProcessorResult result, List<String> errList, List<Content> contents) {
248  dataSourceProcessorDone(dataSourceId, result, errList, contents);
249  }
250  };
251 
252  progressPanel.setStateStarted();
253 
254  // Kick off the DSProcessor
255  dsProcessor.run(progressPanel.getDSPProgressMonitorImpl(), cbObj);
256 
257  }
258 
259  /*
260  * Cancels the data source processing - in case the users presses 'Cancel'
261  */
262  private void cancelDataSourceProcessing(UUID dataSourceId) {
263  dsProcessor.cancel();
264  }
265 
266  /*
267  * Callback for the data source processor. Invoked by the DSP on the EDT
268  * thread, when it finishes processing the data source.
269  */
270  private void dataSourceProcessorDone(UUID dataSourceId, DataSourceProcessorCallback.DataSourceProcessorResult result, List<String> errList, List<Content> contents) {
271  // disable the cleanup task
272  cleanupTask.disable();
273 
274  // Get attention for the process finish
275  // this caused a crash on OS X
276  if (PlatformUtil.isWindowsOS() == true) {
277  java.awt.Toolkit.getDefaultToolkit().beep(); //BEEP!
278  }
279  AddImageWizardAddingProgressVisual panel = progressPanel.getComponent();
280  if (panel != null) {
281  Window w = SwingUtilities.getWindowAncestor(panel);
282  if (w != null) {
283  w.toFront();
284  }
285  }
286  // Tell the panel we're done
287  progressPanel.setStateFinished();
288 
289  //check the result and display to user
290  if (result == DataSourceProcessorCallback.DataSourceProcessorResult.NO_ERRORS) {
291  progressPanel.getComponent().setProgressBarTextAndColor(
292  NbBundle.getMessage(this.getClass(), "AddImageWizardIngestConfigPanel.dsProcDone.noErrs.text"), 100, Color.black);
293  } else {
294  progressPanel.getComponent().setProgressBarTextAndColor(
295  NbBundle.getMessage(this.getClass(), "AddImageWizardIngestConfigPanel.dsProcDone.errs.text"), 100, Color.red);
296  }
297 
298  //if errors, display them on the progress panel
299  boolean critErr = false;
300  if (result == DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS) {
301  critErr = true;
302  }
303  for (String err : errList) {
304  // TBD: there probably should be an error level for each error
305  progressPanel.addErrors(err, critErr);
306  }
307 
308  //notify the UI of the new content added to the case
309  new Thread(() -> {
310  if (!contents.isEmpty()) {
311  Case.getCurrentCase().notifyDataSourceAdded(contents.get(0), dataSourceId);
312  } else {
313  Case.getCurrentCase().notifyFailedAddingDataSource(dataSourceId);
314  }
315  }).start();
316 
317  if (!cancelled) {
318  newContents.clear();
319  newContents.addAll(contents);
320  progressPanel.setStateStarted();
321  startIngest();
322  } else {
323  cancelled = false;
324  }
325 
326  }
327 }

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