Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
AddImageWizardAddingProgressPanel.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 */
19package org.sleuthkit.autopsy.casemodule;
20
21import java.awt.Color;
22import java.awt.Cursor;
23import java.awt.EventQueue;
24import java.awt.Window;
25import java.util.ArrayList;
26import java.util.Collections;
27import java.util.HashSet;
28import java.util.Iterator;
29import java.util.List;
30import java.util.Set;
31import java.util.UUID;
32import java.util.logging.Level;
33import javax.swing.JOptionPane;
34import javax.swing.SwingUtilities;
35import javax.swing.event.ChangeEvent;
36import javax.swing.event.ChangeListener;
37import org.openide.WizardDescriptor;
38import org.openide.util.HelpCtx;
39import org.openide.util.Lookup;
40import org.openide.util.NbBundle;
41import org.openide.windows.WindowManager;
42import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
43import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
44import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
45import org.sleuthkit.autopsy.coreutils.PlatformUtil;
46import org.sleuthkit.autopsy.ingest.IngestJobSettings;
47import org.sleuthkit.autopsy.ingest.IngestManager;
48import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.ShortcutWizardDescriptorPanel;
49import org.sleuthkit.datamodel.Content;
50import org.sleuthkit.autopsy.coreutils.Logger;
51import org.sleuthkit.datamodel.Host;
52
61@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
62class AddImageWizardAddingProgressPanel extends ShortcutWizardDescriptorPanel {
63
64 private boolean readyToIngest = false;
65 // task that will clean up the created database file if the wizard is cancelled before it finishes
66 private AddImageAction.CleanupTask cleanupTask;
67
68 private final AddImageAction addImageAction;
69
70 private DataSourceProcessor dsProcessor = null;
71 private boolean cancelled;
76 private boolean imgAdded = false;
77 private boolean ingested = false;
82 private AddImageWizardAddingProgressVisual component;
83 private final Set<ChangeListener> listeners = new HashSet<>(1); // or can use ChangeSupport in NB 6.0
84 private final List<Content> newContents = Collections.synchronizedList(new ArrayList<>());
85 private final DSPProgressMonitorImpl dspProgressMonitorImpl = new DSPProgressMonitorImpl();
86 private IngestJobSettings ingestJobSettings;
87
88 AddImageWizardAddingProgressPanel(AddImageAction action) {
89 this.addImageAction = action;
90 }
91
92 DSPProgressMonitorImpl getDSPProgressMonitorImpl() {
93 return dspProgressMonitorImpl;
94 }
95
97
98 @Override
99 public void setIndeterminate(final boolean indeterminate) {
100 // update the progress bar asynchronously
101 EventQueue.invokeLater(new Runnable() {
102 @Override
103 public void run() {
104 getComponent().getProgressBar().setIndeterminate(indeterminate);
105 }
106 });
107 }
108
109 @Override
110 public void setProgress(final int progress) {
111 // update the progress bar asynchronously
112 EventQueue.invokeLater(new Runnable() {
113 @Override
114 public void run() {
115 getComponent().getProgressBar().setValue(progress);
116 }
117 });
118 }
119
120 @Override
121 public void setProgressMax(final int max) {
122 // update the progress bar asynchronously
123 EventQueue.invokeLater(new Runnable() {
124 @Override
125 public void run() {
126 getComponent().getProgressBar().setMaximum(max);
127 }
128 });
129 }
130
131 @Override
132 public void setProgressText(final String text) {
133 // update the progress UI asynchronously
134 EventQueue.invokeLater(new Runnable() {
135 @Override
136 public void run() {
137 getComponent().setProgressMsgText(text);
138 }
139 });
140 }
141
142 }
143
154 @Override
155 public AddImageWizardAddingProgressVisual getComponent() {
156 if (component == null) {
157 component = new AddImageWizardAddingProgressVisual();
158 }
159 return component;
160 }
161
168 @Override
169 public HelpCtx getHelp() {
170 // Show no Help button for this panel:
171 return HelpCtx.DEFAULT_HELP;
172 }
173
180 @Override
181 public boolean isValid() {
182 // set the focus to the next button of the wizard dialog if it's enabled
183 if (imgAdded) {
184 Lookup.getDefault().lookup(AddImageAction.class).requestFocusButton(
185 NbBundle.getMessage(this.getClass(), "AddImageWizardAddingProgressPanel.isValid.focusNext"));
186 }
187
188 return imgAdded;
189 }
190
194 void setStateStarted() {
195 component.getProgressBar().setIndeterminate(true);
196 component.setProgressBarTextAndColor(
197 NbBundle.getMessage(this.getClass(), "AddImageWizardAddingProgressPanel.stateStarted.progressBarText"), 0, Color.black);
198 }
199
203 void setStateFinished() {
204 imgAdded = true;
205 getComponent().setStateFinished();
206 fireChangeEvent();
207 }
208
214 @Override
215 public final void addChangeListener(ChangeListener l) {
216 synchronized (listeners) {
217 listeners.add(l);
218 }
219 }
220
226 @Override
227 public final void removeChangeListener(ChangeListener l) {
228 synchronized (listeners) {
229 listeners.remove(l);
230 }
231 }
232
237 protected final void fireChangeEvent() {
238 Iterator<ChangeListener> it;
239 synchronized (listeners) {
240 it = new HashSet<>(listeners).iterator();
241 }
242 ChangeEvent ev = new ChangeEvent(this);
243 while (it.hasNext()) {
244 it.next().stateChanged(ev);
245 }
246 }
247
254 @Override
255 public void readSettings(WizardDescriptor settings) {
256 // Start ingest if it hasn't already been started
257 startIngest();
258 settings.setOptions(new Object[]{WizardDescriptor.PREVIOUS_OPTION, WizardDescriptor.NEXT_OPTION, WizardDescriptor.FINISH_OPTION, WizardDescriptor.CANCEL_OPTION});
259 if (imgAdded) {
260 getComponent().setStateFinished();
261 }
262 }
263
264 void resetReadyToIngest() {
265 this.readyToIngest = false;
266 }
267
268 void setIngestJobSettings(IngestJobSettings ingestSettings) {
269 showWarnings(ingestSettings);
270 this.readyToIngest = true;
271 this.ingestJobSettings = ingestSettings;
272 }
273
280 @Override
281 public void storeSettings(WizardDescriptor settings) {
282 //why did we do this? -jm
283 // getComponent().resetInfoPanel();
284 }
285
295 void addErrors(String errorString, boolean critical) {
296 getComponent().showErrors(errorString, critical);
297 }
298
303 private void startIngest() {
304 if (!newContents.isEmpty() && readyToIngest && !ingested) {
305 ingested = true;
306 if (dsProcessor != null && !dsProcessor.supportsIngestStream()) {
307 IngestManager.getInstance().queueIngestJob(newContents, ingestJobSettings);
308 }
309 setStateFinished();
310 }
311 }
312
313 private static void showWarnings(IngestJobSettings ingestJobSettings) {
314 List<String> warnings = ingestJobSettings.getWarnings();
315 if (warnings.isEmpty() == false) {
316 StringBuilder warningMessage = new StringBuilder();
317 for (String warning : warnings) {
318 warningMessage.append(warning).append("\n");
319 }
320 JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), warningMessage.toString());
321 }
322 }
323
333 void startDataSourceProcessing(DataSourceProcessor dsp, Host selectedHost) {
334 if (dsProcessor == null) { //this can only be run once
335 final UUID dataSourceId = UUID.randomUUID();
336 newContents.clear();
337 cleanupTask = null;
338 dsProcessor = dsp;
339 new Thread(() -> {
340 // Add a cleanup task to interrupt the background process if the
341 // wizard exits while the background process is running.
342 cleanupTask = addImageAction.new CleanupTask() {
343 @Override
344 void cleanup() throws Exception {
345 WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
346 cancelDataSourceProcessing(dataSourceId);
347 cancelled = true;
348 WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
349 }
350 };
351
352 cleanupTask.enable();
353
354 try {
356 } catch (NoCurrentCaseException ex) {
357 Logger.getLogger(AddImageWizardAddingProgressVisual.class.getName()).log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS
358 }
359
361 @Override
362 public void doneEDT(DataSourceProcessorCallback.DataSourceProcessorResult result, List<String> errList, List<Content> contents) {
363 dataSourceProcessorDone(dataSourceId, result, errList, contents);
364 }
365 };
366
367 // Kick off the DSProcessor
368 if (dsProcessor.supportsIngestStream()) {
369 // Set readyToIngest to false to prevent the wizard from starting ingest a second time.
370 readyToIngest = false;
371 dsProcessor.runWithIngestStream(selectedHost, ingestJobSettings, getDSPProgressMonitorImpl(), cbObj);
372 } else {
373 dsProcessor.run(selectedHost, getDSPProgressMonitorImpl(), cbObj);
374 }
375 }).start();
376 setStateStarted();
377 }
378 }
379
380 /*
381 * Cancels the data source processing - in case the users presses 'Cancel'
382 */
383 private void cancelDataSourceProcessing(UUID dataSourceId) {
384 dsProcessor.cancel();
385 }
386
387 /*
388 * Callback for the data source processor. Invoked by the DSP on the EDT
389 * thread, when it finishes processing the data source.
390 */
391 private void dataSourceProcessorDone(UUID dataSourceId, DataSourceProcessorCallback.DataSourceProcessorResult result, List<String> errList, List<Content> contents) {
392 // disable the cleanup task
393 cleanupTask.disable();
394
395 // Get attention for the process finish
396 // this caused a crash on OS X
397 if (PlatformUtil.isWindowsOS() == true) {
398 java.awt.Toolkit.getDefaultToolkit().beep(); //BEEP!
399 }
400 AddImageWizardAddingProgressVisual panel = getComponent();
401 if (panel != null) {
402 Window w = SwingUtilities.getWindowAncestor(panel);
403 if (w != null) {
404 w.toFront();
405 }
406 }
407 // Tell the panel we're done
408 setStateFinished();
409
410 //check the result and display to user
412 getComponent().setProgressBarTextAndColor(
413 NbBundle.getMessage(this.getClass(), "AddImageWizardIngestConfigPanel.dsProcDone.noErrs.text"), 100, Color.black);
414 } else {
415 getComponent().setProgressBarTextAndColor(
416 NbBundle.getMessage(this.getClass(), "AddImageWizardIngestConfigPanel.dsProcDone.errs.text"), 100, Color.red);
417 }
418
419 //if errors, display them on the progress panel
420 boolean critErr = false;
422 critErr = true;
423 }
424 for (String err : errList) {
425 // TBD: there probably should be an error level for each error
426 addErrors(err, critErr);
427 }
428 final Level level = critErr ? Level.SEVERE : Level.WARNING;
429 new Thread(() -> {
430 //log error messages as Severe if there was a critical error otherwise as Warning.
431 //logging performed off of UI thread
432 for (String err : errList) {
433 Logger.getLogger(AddImageWizardAddingProgressVisual.class.getName()).log(level, "DatasourceID: {0} Error Message: {1}", new Object[]{dataSourceId.toString(), err});
434 }
435 //notify the UI of the new content added to the case
436 try {
437 if (!contents.isEmpty()) {
438 Case.getCurrentCaseThrows().notifyDataSourceAdded(contents.get(0), dataSourceId);
439 } else {
441 }
442 } catch (NoCurrentCaseException ex) {
443 Logger.getLogger(AddImageWizardAddingProgressVisual.class.getName()).log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS
444 }
445 }).start();
446
447 if (!cancelled) {
448 newContents.clear();
449 newContents.addAll(contents);
450 setStateStarted();
451 startIngest();
452 } else {
453 cancelled = false;
454 }
455
456 }
457}
void notifyFailedAddingDataSource(UUID addingDataSourceEventId)
Definition Case.java:1786
void notifyAddingDataSource(UUID eventId)
Definition Case.java:1770
void notifyDataSourceAdded(Content dataSource, UUID addingDataSourceEventId)
Definition Case.java:1801
synchronized static Logger getLogger(String name)
Definition Logger.java:124
static synchronized IngestManager getInstance()
void queueIngestJob(Collection< Content > dataSources, IngestJobSettings settings)

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.