Revert "Fix thread safety, clean up add data source wizard classes"

This reverts commit b93d45fbf12824d7172ac6297ce4e6c24fbe1ed4.
This commit is contained in:
Richard Cordovano 2016-01-20 17:30:29 -05:00
parent fc6f972e54
commit eda180e34f
7 changed files with 550 additions and 474 deletions

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2014 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -21,11 +21,13 @@ package org.sleuthkit.autopsy.casemodule;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.logging.Level;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.openide.DialogDisplayer;
@ -35,91 +37,139 @@ import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.Presenter;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.datamodel.Image;
/**
* An action that adds a data source to the current case.
* The action to add an image to the current Case. This action should be
* disabled on creation and it will be enabled on new case creation or case
* opened.
*
* RC: This action needs to be enabled and disabled as cases are opened and
* closed. Currently this is done using
* CallableSystemAction.get(AddImageAction.class).setEnabled().
* @author jantonius
*/
// TODO: need annotation because there's a "Lookup.getDefault().lookup(AddImageAction.class)"
// used in AddImageWizardPanel1 (among other places). It really shouldn't be done like that.
@ServiceProvider(service = AddImageAction.class)
public final class AddImageAction extends CallableSystemAction implements Presenter.Toolbar {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(AddImageAction.class.getName());
private final ChangeSupport cleanupSupport;
private final JButton toolbarButton;
// Keys into the WizardDescriptor properties that pass information between stages of the wizard
// <TYPE>: <DESCRIPTION>
// String: time zone that the image is from
static final String TIMEZONE_PROP = "timeZone"; //NON-NLS
// String[]: array of paths to each data source selected
static final String DATASOURCEPATH_PROP = "dataSrcPath"; //NON-NLS
// String data source type selected
static final String DATASOURCETYPE_PROP = "dataSrcType"; //NON-NLS
// CleanupTask: task to clean up the database file if wizard errors/is cancelled after it is created
static final String IMAGECLEANUPTASK_PROP = "finalFileCleanup"; //NON-NLS
// int: the next availble id for a new image
static final String IMAGEID_PROP = "imageId"; //NON-NLS
// AddImageProcess: the next availble id for a new image
static final String PROCESS_PROP = "process"; //NON-NLS
// boolean: whether or not to lookup files in the hashDB
static final String LOOKUPFILES_PROP = "lookupFiles"; //NON-NLS
// boolean: whether or not to skip processing orphan files on FAT filesystems
static final String NOFATORPHANS_PROP = "nofatorphans"; //NON-NLS
static final Logger logger = Logger.getLogger(AddImageAction.class.getName());
private WizardDescriptor wizardDescriptor;
private WizardDescriptor.Iterator<WizardDescriptor> iterator;
private Dialog dialog;
private JButton toolbarButton = new JButton();
/**
* Constructs an action that adds a data source to the current case.
* The constructor for AddImageAction class
*/
public AddImageAction() {
cleanupSupport = new ChangeSupport(this);
putValue(Action.NAME, NbBundle.getMessage(AddImageAction.class, "CTL_AddImage"));
toolbarButton = new JButton();
toolbarButton.addActionListener(AddImageAction.this::actionPerformed);
setEnabled(false);
putValue(Action.NAME, NbBundle.getMessage(AddImageAction.class, "CTL_AddImage")); // set the action Name
// set the action for the toolbar button
toolbarButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
AddImageAction.this.actionPerformed(e);
}
});
this.setEnabled(false); // disable this action class
}
/**
* Displays the first panel of the add data source wizard.
* Pop-up the "Add Image" wizard panel.
*
* @param notUsed An action event, may be null.
* @param e
*/
@Override
public void actionPerformed(ActionEvent notUsed) {
/*
* If ingest is running, confirm that the user wants to add another data
* source at this time, instead of waiting for the current ingest job to
* complete.
*/
public void actionPerformed(ActionEvent e) {
if (IngestManager.getInstance().isIngestRunning()) {
if (JOptionPane.showConfirmDialog(null,
NbBundle.getMessage(this.getClass(), "AddImageAction.ingestConfig.ongoingIngest.msg"),
NbBundle.getMessage(this.getClass(), "AddImageAction.ingestConfig.ongoingIngest.title"),
final String msg = NbBundle.getMessage(this.getClass(), "AddImageAction.ingestConfig.ongoingIngest.msg");
if (JOptionPane.showConfirmDialog(null, msg,
NbBundle.getMessage(this.getClass(),
"AddImageAction.ingestConfig.ongoingIngest.title"),
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.NO_OPTION) {
return;
}
}
/*
* Construct and display the wizard.
*/
iterator = new AddImageWizardIterator();
iterator = new AddImageWizardIterator(this);
wizardDescriptor = new WizardDescriptor(iterator);
wizardDescriptor.setTitle(NbBundle.getMessage(this.getClass(), "AddImageAction.wizard.title"));
Dialog dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor);
wizardDescriptor.putProperty(NAME, e);
if (dialog != null) {
dialog.setVisible(false); // hide the old one
}
dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor);
dialog.setVisible(true);
dialog.toFront();
/*
* Run any registered cleanup tasks by firing a change event. This will
* cause the stateChanged method of any implementations of the inner,
* abstract CleanupTask class to call their cleanup methods (assuming
* they have not done an override of stateChanged), after which the
* CleanupTasks are unregistered.
*
* RC: This is a convoluted and error-prone way to implement clean up.
* Fortunately, it is confined to this package.
*/
cleanupSupport.fireChange();
// Do any cleanup that needs to happen (potentially: stopping the
//add-image process, reverting an image)
runCleanupTasks();
}
/**
* @inheritDoc
* Closes the current dialog and wizard, and opens a new one. Used in the
* "Add another image" action on the last panel
*/
void restart() {
// Simulate clicking finish for the current dialog
wizardDescriptor.setValue(WizardDescriptor.FINISH_OPTION);
dialog.setVisible(false);
// let the previous call to AddImageAction.actionPerformed() finish up
// after the wizard, this will run when its it's done
final Runnable r = new Runnable() {
@Override
public void run() {
actionPerformed(null);
}
};
SwingUtilities.invokeLater(r);
}
public interface IndexImageTask {
void runTask(Image newImage);
}
/**
* This method does nothing. Use the "actionPerformed(ActionEvent e)"
* instead of this method.
*/
@Override
public void performAction() {
actionPerformed(null);
}
/**
* @inheritDoc
* Gets the name of this action. This may be presented as an item in a menu.
*
* @return actionName
*/
@Override
public String getName() {
@ -127,7 +177,9 @@ public final class AddImageAction extends CallableSystemAction implements Presen
}
/**
* @inheritDoc
* Gets the HelpCtx associated with implementing object
*
* @return HelpCtx or HelpCtx.DEFAULT_HELP
*/
@Override
public HelpCtx getHelpCtx() {
@ -135,7 +187,9 @@ public final class AddImageAction extends CallableSystemAction implements Presen
}
/**
* @inheritDoc
* Returns the toolbar component of this action
*
* @return component the toolbar button
*/
@Override
public Component getToolbarPresenter() {
@ -146,7 +200,9 @@ public final class AddImageAction extends CallableSystemAction implements Presen
}
/**
* @inheritDoc
* Set this action to be enabled/disabled
*
* @param value whether to enable this action or not
*/
@Override
public void setEnabled(boolean value) {
@ -155,80 +211,68 @@ public final class AddImageAction extends CallableSystemAction implements Presen
}
/**
* Does nothing, do not use.
* Set the focus to the button of the given name on this wizard dialog.
*
* @deprecated Classes in this package may call requestFocusForWizardButton
* instead.
* Note: the name of the buttons that available are "Next >", "< Back",
* "Cancel", and "Finish". If you change the name of any of those buttons,
* use the latest name instead.
*
* @param buttonText the text of the button
*/
@Deprecated
public void requestFocusButton(String buttonText) {
}
/**
* Requests focus for an add data source wizard button.
*
* @param buttonText The text of the button.
*/
void requestFocusForWizardButton(String buttonText) {
for (Object wizardButton : wizardDescriptor.getOptions()) {
JButton button = (JButton) wizardButton;
if (button.getText().equals(buttonText)) {
button.setDefaultCapable(true);
button.requestFocus();
// get all buttons on this wizard panel
Object[] wizardButtons = wizardDescriptor.getOptions();
for (int i = 0; i < wizardButtons.length; i++) {
JButton tempButton = (JButton) wizardButtons[i];
if (tempButton.getText().equals(buttonText)) {
tempButton.setDefaultCapable(true);
tempButton.requestFocus();
}
}
}
/**
* Enabled instances of this class are called to do clean up after the add
* data source wizard is closed. The instances are disabled after the
* cleanUp method is called. Implementations should not override
* stateChanged, and should not re-enable themselves after cleanUp is
* called. To stop cleanUp being called, call disable before the wizard is
* dismissed.
* Run and clear any cleanup tasks for wizard closing that might be
* registered. This should be run even when the wizard exits cleanly, so
* that no cleanup actions remain the next time the wizard is run.
*/
private void runCleanupTasks() {
cleanupSupport.fireChange();
}
ChangeSupport cleanupSupport = new ChangeSupport(this);
/**
* Instances of this class implement the cleanup() method to run cleanup
* code when the wizard exits.
*
* Instances must be constructed using a reference to an AddImageAction
* object because this is a non-static inner class.
* After enable() has been called on an instance it will run once after the
* wizard closes (on both a cancel and a normal finish).
*
* RC: This is a convoluted and error-prone way to implement clean up.
* Fortunately, it is confined to this package.
* If disable() is called before the wizard exits, the task will not run.
*/
abstract class CleanupTask implements ChangeListener {
@Override
public void stateChanged(ChangeEvent e) {
/*
* actionPerformed fires this event after the add data source wizard
* is closed.
*/
// fired by AddImageAction.runCleanupTasks() after the wizard closes
try {
cleanup();
} catch (Exception ex) {
logger.log(Level.SEVERE, "Error cleaning in add data source wizard clean up task", ex); //NON-NLS
Logger logger = Logger.getLogger(this.getClass().getName());
logger.log(Level.WARNING, "Error cleaning up from wizard.", ex); //NON-NLS
} finally {
/*
* Clean up tasks should only be done exactly once.
*/
disable();
disable(); // cleanup tasks should only run once.
}
}
/**
* Adds this task to the list of tasks to be done when the wizard
* closes.
* Add task to the enabled list to run when the wizard closes.
*/
void enable() {
public void enable() {
cleanupSupport.addChangeListener(this);
}
/**
* Removes this task from the list of tasks to be done when the wizard
* closes.
*/
void disable() {
cleanupSupport.removeChangeListener(this);
}
/**
* Performs cleanup action when called
*
@ -236,12 +280,11 @@ public final class AddImageAction extends CallableSystemAction implements Presen
*/
abstract void cleanup() throws Exception;
/**
* Remove task from the enabled list.
*/
public void disable() {
cleanupSupport.removeChangeListener(this);
}
}
@Deprecated
public interface IndexImageTask {
void runTask(Image newImage);
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2014 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -20,97 +20,105 @@ package org.sleuthkit.autopsy.casemodule;
import java.awt.Color;
import java.awt.EventQueue;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.openide.WizardDescriptor;
import org.openide.util.ChangeSupport;
import org.openide.util.HelpCtx;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
/**
* The third and final panel of the add data source wizard. The visual component
* of this panel displays a progress bar that is managed by the previous panel
* and the data source processor.
* The final panel of the add image wizard. It displays a progress bar and
* status updates.
*
* All the real work is kicked off in the previous panel:
* {@link AddImageWizardIngestConfigPanel} (which is a bit weird if you ask m
* -jm)
*/
// All the real work is kicked off in the previous panel:
// {@link AddImageWizardIngestConfigPanel} (which is a bit weird if you ask m
// -jm)
final class AddImageWizardAddingProgressPanel implements WizardDescriptor.FinishablePanel<WizardDescriptor> {
class AddImageWizardAddingProgressPanel implements WizardDescriptor.FinishablePanel<WizardDescriptor> {
private final ChangeSupport changeSupport;
private final DSPProgressMonitorImpl dspProgressMonitor = new DSPProgressMonitorImpl();
/**
* flag to indicate that the image adding process is finished and this panel
* is completed(valid)
*/
private boolean imgAdded = false;
/**
* The visual component that displays this panel. If you need to access the
* component from this class, just use getComponent().
*/
private AddImageWizardAddingProgressVisual component;
private boolean dataSourceAdded = false;
private final Set<ChangeListener> listeners = new HashSet<>(1); // or can use ChangeSupport in NB 6.0
/**
* Constructs an instance of the third and final panel of the add data
* source wizard.
*/
AddImageWizardAddingProgressPanel() {
changeSupport = new ChangeSupport(this);
private DSPProgressMonitorImpl dspProgressMonitorImpl = new DSPProgressMonitorImpl();
public DSPProgressMonitorImpl getDSPProgressMonitorImpl() {
return dspProgressMonitorImpl;
}
/**
* Gets the data source progress monitor. Allows the previous panel to hand
* off the progress monitor to the data source processor.
*/
DSPProgressMonitorImpl getDSPProgressMonitor() {
return dspProgressMonitor;
}
/**
* A data source processor progress monitor that acts as a bridge between
* the data source processor started by the previous panel and the progress
* bar displayed by the visual component of this panel.
*/
private class DSPProgressMonitorImpl implements DataSourceProcessorProgressMonitor {
@Override
public void setIndeterminate(final boolean indeterminate) {
EventQueue.invokeLater(() -> {
getComponent().getProgressBar().setIndeterminate(indeterminate);
// update the progress bar asynchronously
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
getComponent().getProgressBar().setIndeterminate(indeterminate);
}
});
}
@Override
public void setProgress(final int progress) {
// update the progress bar asynchronously
EventQueue.invokeLater(() -> {
getComponent().getProgressBar().setValue(progress);
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
getComponent().getProgressBar().setValue(progress);
}
});
}
@Override
public void setProgressText(final String text) {
// update the progress UI asynchronously
EventQueue.invokeLater(() -> {
getComponent().setProgressMsgText(text);
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
getComponent().setProgressMsgText(text);
}
});
}
}
/**
* Gets the visual component for the panel. In this template, the component
* Get the visual component for the panel. In this template, the component
* is kept separate. This can be more efficient: if the wizard is created
* but never displayed, or not all panels are displayed, it is better to
* create only those which really need to be visible.
*
* @return The UI component of this wizard panel.
* It also separates the view from the control - jm
*
* @return component the UI component of this wizard panel
*/
@Override
public AddImageWizardAddingProgressVisual getComponent() {
if (null == component) {
if (component == null) {
component = new AddImageWizardAddingProgressVisual();
}
return component;
}
/**
* Gets the help for this panel. When the panel is active, this is used as
* the help for the wizard dialog.
* Help for this panel. When the panel is active, this is used as the help
* for the wizard dialog.
*
* @return The help for this panel
* @return HelpCtx.DEFAULT_HELP the help for this panel
*/
@Override
public HelpCtx getHelp() {
@ -126,12 +134,17 @@ final class AddImageWizardAddingProgressPanel implements WizardDescriptor.Finish
*/
@Override
public boolean isValid() {
return dataSourceAdded;
// set the focus to the next button of the wizard dialog if it's enabled
if (imgAdded) {
Lookup.getDefault().lookup(AddImageAction.class).requestFocusButton(
NbBundle.getMessage(this.getClass(), "AddImageWizardAddingProgressPanel.isValid.focusNext"));
}
return imgAdded;
}
/**
* Makes the progress bar of the visual component of this panel indicate
* that the data source processor is running.
* Updates the UI to display the add image process has begun.
*/
void setStateStarted() {
component.getProgressBar().setIndeterminate(true);
@ -140,85 +153,94 @@ final class AddImageWizardAddingProgressPanel implements WizardDescriptor.Finish
}
/**
* Makes the progress bar of the visual component of this panel indicate
* that the data source processor is not running.
* Updates the UI to display the add image process is over.
*/
void setStateFinished() {
dataSourceAdded = true;
imgAdded = true;
getComponent().setStateFinished();
fireChangeEvent();
}
/**
* @inheritDoc5
* Adds a listener to changes of the panel's validity.
*
* @param l the change listener to add
*/
@Override
public final void addChangeListener(ChangeListener listener) {
changeSupport.addChangeListener(listener);
public final void addChangeListener(ChangeListener l) {
synchronized (listeners) {
listeners.add(l);
}
}
/**
* @inheritDoc
* Removes a listener to changes of the panel's validity.
*
* @param l the change listener to move
*/
@Override
public final void removeChangeListener(ChangeListener listener) {
changeSupport.removeChangeListener(listener);
public final void removeChangeListener(ChangeListener l) {
synchronized (listeners) {
listeners.remove(l);
}
}
/**
* @inheritDoc
* This method is auto-generated. It seems that this method is used to
* listen to any change in this wizard panel.
*/
protected final void fireChangeEvent() {
changeSupport.fireChange();
Iterator<ChangeListener> it;
synchronized (listeners) {
it = new HashSet<ChangeListener>(listeners).iterator();
}
ChangeEvent ev = new ChangeEvent(this);
while (it.hasNext()) {
it.next().stateChanged(ev);
}
}
/**
* Provides the wizard panel with the current data--either the default data
* or already-modified settings, if the user used the previous and/or next
* buttons. This method can be called multiple times on one instance of
* WizardDescriptor.Panel.
* Load the image locations from the WizardDescriptor settings object, and
* the
*
* @param settings The settings.
* @param settings the setting to be read from
*/
@Override
public void readSettings(WizardDescriptor settings) {
settings.setOptions(new Object[]{WizardDescriptor.PREVIOUS_OPTION, WizardDescriptor.NEXT_OPTION, WizardDescriptor.FINISH_OPTION, WizardDescriptor.CANCEL_OPTION});
if (dataSourceAdded) {
if (imgAdded) {
getComponent().setStateFinished();
}
}
/**
* Provides the wizard panel with the opportunity to update the settings
* with its current customized state. Rather than updating its settings with
* every change in the GUI, it should collect them, and then only save them
* when requested to by this method. This method can be called multiple
* times on one instance of WizardDescriptor.Panel.
* this doesn't appear to store anything? plus, there are no settings in
* this panel -jm
*
* @param settings the setting to be stored to
*/
@Override
public void storeSettings(WizardDescriptor settings) {
//why did we do this? -jm
// getComponent().resetInfoPanel();
}
/**
* Displays an error message from the data source processor for the data
* source being added.
* forward errors to visual component
*
* @param errorString The error message to be displayed
* @param critical True if this is a critical error
* should this be modified to handle a list of errors? -jm
*
*
* @param errorString the error string to be displayed
* @param critical true if this is a critical error
*/
// Should this be modified to handle a list of errors? -jm
void displayDataSourceProcessorError(String errorString, boolean critical) {
void addErrors(String errorString, boolean critical) {
getComponent().showErrors(errorString, critical);
}
/**
* @inheritDoc
*/
@Override
public boolean isFinishPanel() {
return true;
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -20,43 +20,55 @@ package org.sleuthkit.autopsy.casemodule;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Level;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.openide.WizardDescriptor;
import org.openide.util.HelpCtx;
import org.openide.util.Lookup;
import org.openide.windows.WindowManager;
import java.awt.Cursor;
import org.openide.util.ChangeSupport;
import org.openide.util.actions.CallableSystemAction;
/**
* The first panel of the add data source wizard. The visual component of this
* panel allows a user to select data sources to add to the current case.
* The "Add Image" wizard panel1 handling the logic of selecting image file(s)
* to add to Case, and pick the time zone.
*/
final class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel<WizardDescriptor>, PropertyChangeListener {
private AddImageWizardChooseDataSourceVisual component;
private final ChangeSupport changeSupport;
private boolean nextButtonIsEnabled = false;
class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel<WizardDescriptor>, PropertyChangeListener {
/**
* Constructs an instance of the first panel of the add data source wizard.
* The visual component that displays this panel. If you need to access the
* component from this class, just use getComponent().
*/
AddImageWizardChooseDataSourcePanel() {
changeSupport = new ChangeSupport(this);
private AddImageWizardAddingProgressPanel progressPanel;
private AddImageWizardChooseDataSourceVisual component;
private boolean isNextEnable = false;
private static final String PROP_LASTDATASOURCE_PATH = "LBL_LastDataSource_PATH"; //NON-NLS
private static final String PROP_LASTDATASOURCE_TYPE = "LBL_LastDataSource_TYPE"; //NON-NLS
// paths to any set hash lookup databases (can be null)
private String NSRLPath, knownBadPath;
AddImageWizardChooseDataSourcePanel(AddImageWizardAddingProgressPanel proPanel) {
this.progressPanel = proPanel;
}
/**
* Gets the visual component for the panel. The component is kept separate.
* This can be more efficient: if the wizard is created but never displayed,
* or not all panels are displayed, it is better to create only those which
* really need to be visible.
* Get the visual component for the panel. In this template, the component
* is kept separate. This can be more efficient: if the wizard is created
* but never displayed, or not all panels are displayed, it is better to
* create only those which really need to be visible.
*
* @return The UI component of this wizard panel.
* @return component the UI component of this wizard panel
*/
@Override
public AddImageWizardChooseDataSourceVisual getComponent() {
if (null == component) {
if (component == null) {
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
component = new AddImageWizardChooseDataSourceVisual(this);
}
@ -65,103 +77,156 @@ final class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Pane
}
/**
* Gets the help for this panel. When the panel is active, this is used as
* the help for the wizard dialog.
* Help for this panel. When the panel is active, this is used as the help
* for the wizard dialog.
*
* @return The help for this panel
* @return HelpCtx.DEFAULT_HELP the help for this panel
*/
@Override
public HelpCtx getHelp() {
// Show no Help button for this panel:
return HelpCtx.DEFAULT_HELP;
// If you have context help:
// return new HelpCtx(SampleWizardPanel1.class);
}
/**
* Tests whether the panel is finished and it is safe to proceed to the next
* one. If the panel is valid, the "Next" button will be enabled.
*
* Tests whether or not the panel is finished. If the panel is valid, the
* "Finish" button will be enabled.
*
* @return True or false.
* @return boolean true if all the fields are correctly filled, false
* otherwise
*/
@Override
public boolean isValid() {
// If it is always OK to press Next or Finish, then:
// return true;
// If it depends on some condition (form filled out...), then:
// return someCondition();
// and when this condition changes (last form field filled in...) then:
// fireChangeEvent();
/*
* When it is valid, the visual component calls enableNextButton to set
* this flag.
*/
return nextButtonIsEnabled;
return isNextEnable;
}
/**
* Moves the keyboard focus to the next button of the wizard.
* Move the keyboard focus to the next button
*/
void moveFocusToNext() {
if (nextButtonIsEnabled) {
CallableSystemAction.get(AddImageAction.class).requestFocusForWizardButton(
// set the focus to the next button of the wizard dialog if it's enabled
if (isNextEnable) {
Lookup.getDefault().lookup(AddImageAction.class).requestFocusButton(
NbBundle.getMessage(this.getClass(), "AddImageWizardChooseDataSourcePanel.moveFocusNext"));
}
}
/**
* Enables the "Next" button and fires a change event to update the UI.
* Enable the "Next" button and fireChangeEvent to update the GUI
*
* @param isEnabled True if next button should be enabled, false otherwise.
* @param isEnabled true if next button can be enabled, false otherwise
*/
void enableNextButton(boolean isEnabled) {
nextButtonIsEnabled = isEnabled;
public void enableNextButton(boolean isEnabled) {
isNextEnable = isEnabled;
fireChangeEvent();
}
private final Set<ChangeListener> listeners = new HashSet<ChangeListener>(1); // or can use ChangeSupport in NB 6.0
/**
* @inheritDoc
* Adds a listener to changes of the panel's validity.
*
* @param l the change listener to add
*/
@Override
public final void addChangeListener(ChangeListener listener) {
changeSupport.addChangeListener(listener);
public final void addChangeListener(ChangeListener l) {
synchronized (listeners) {
listeners.add(l);
}
}
/**
* @inheritDoc
* Removes a listener to changes of the panel's validity.
*
* @param l the change listener to move
*/
@Override
public final void removeChangeListener(ChangeListener listener) {
changeSupport.removeChangeListener(listener);
public final void removeChangeListener(ChangeListener l) {
synchronized (listeners) {
listeners.remove(l);
}
}
/**
* @inheritDoc
* This method is auto-generated. It seems that this method is used to
* listen to any change in this wizard panel.
*/
protected final void fireChangeEvent() {
changeSupport.fireChange();
Iterator<ChangeListener> it;
synchronized (listeners) {
it = new HashSet<ChangeListener>(listeners).iterator();
}
ChangeEvent ev = new ChangeEvent(this);
while (it.hasNext()) {
it.next().stateChanged(ev);
}
}
// You can use a settings object to keep track of state. Normally the
// settings object will be the WizardDescriptor, so you can use
// WizardDescriptor.getProperty & putProperty to store information entered
// by the user.
/**
* Provides the wizard panel with the current data--either the default data
* or already-modified settings, if the user used the previous and/or next
* buttons. This method can be called multiple times on one instance of
* WizardDescriptor.Panel.
* WizardDescriptor.Panel. s
*
* @param settings The settings.
* @param settings the setting to be read from
*/
@Override
public void readSettings(WizardDescriptor settings) {
//reset settings if supports it
//getComponent().reset();
// Prepopulate the image directory from the properties file
try {
// Load hash database settings, enable or disable the checkbox
this.NSRLPath = null;
this.knownBadPath = null;
//JCheckBox lookupFilesCheckbox = component.getLookupFilesCheckbox();
//lookupFilesCheckbox.setSelected(false);
//lookupFilesCheckbox.setEnabled(this.NSRLPath != null || this.knownBadPath != null);
// If there is a process object in the settings, revert it and remove it from the settings
AddImageAction.CleanupTask cleanupTask = (AddImageAction.CleanupTask) settings.getProperty(AddImageAction.IMAGECLEANUPTASK_PROP);
if (cleanupTask != null) {
try {
cleanupTask.cleanup();
} catch (Exception ex) {
Logger logger = Logger.getLogger(AddImageWizardChooseDataSourcePanel.class.getName());
logger.log(Level.WARNING, "Error cleaning up image task", ex); //NON-NLS
} finally {
cleanupTask.disable();
}
}
} catch (Exception e) {
}
}
/**
* @inheritDoc
* Provides the wizard panel with the opportunity to update the settings
* with its current customized state. Rather than updating its settings with
* every change in the GUI, it should collect them, and then only save them
* when requested to by this method. This method can be called multiple
* times on one instance of WizardDescriptor.Panel.
*
* @param settings the setting to be stored to
*/
@Override
public void storeSettings(WizardDescriptor settings) {
return;
}
/**
* @inheritDoc
* The "listener" for any property change in this panel. Any property
* changes will invoke the "fireChangeEvent()" method.
*
* @param evt the property change event
*/
@Override
public void propertyChange(PropertyChangeEvent evt) {

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2015 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -31,9 +31,7 @@ import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeListener;
import org.openide.WizardDescriptor;
import org.openide.util.ChangeSupport;
import org.openide.util.HelpCtx;
import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
@ -42,108 +40,80 @@ import org.sleuthkit.autopsy.ingest.IngestJobSettingsPanel;
import org.sleuthkit.autopsy.ingest.IngestManager;
/**
* The second panel of the add data source wizard. The visual component of this
* panel allows a user to configure the ingest modules for the ingest job for
* the data source, and this panel both runs the data source processor and
* starts the ingest job.
* second panel of add image wizard, allows user to configure ingest modules.
*
* TODO: review this for dead code. think about moving logic of adding image to
* 3rd panel( {@link AddImageWizardAddingProgressPanel}) separate class -jm
*/
// JM: Think about moving the logic of adding image to the 3rd panel
// ( {@link AddImageWizardAddingProgressPanel})
final class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDescriptor> {
class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDescriptor> {
private final AddImageWizardChooseDataSourcePanel selectDataSourcePanel;
private final AddImageWizardAddingProgressPanel progressPanel;
private final ChangeSupport changeSupport;
private final List<Content> newContents;
private final IngestJobSettingsPanel ingestJobSettingsPanel;
private Component component;
private volatile boolean ingestModulesConfigured;
private volatile boolean ingestJobStarted;
private AddImageAction.CleanupTask cleanupTask;
private DataSourceProcessor dsProcessor;
/**
* Constructs an instance of The second panel of the add data source wizard.
* The visual component of this panel allows a user to configure the ingest
* modules for the ingest job for the data source.
*
* @param selectDataSourcePanel The second panel of the add data source
* wizard.
* @param progressPanel The third panel of the data source wizard.
* The visual component that displays this panel. If you need to access the
* component from this class, just use getComponent().
*/
AddImageWizardIngestConfigPanel(AddImageWizardChooseDataSourcePanel selectDataSourcePanel, AddImageWizardAddingProgressPanel progressPanel) {
this.selectDataSourcePanel = selectDataSourcePanel;
this.progressPanel = progressPanel;
changeSupport = new ChangeSupport(this);
private Component component = null;
/*
* Create a collection to receive the Content objects returned by the
* data source processor.
*/
newContents = Collections.synchronizedList(new ArrayList<Content>());
private final List<Content> newContents = Collections.synchronizedList(new ArrayList<Content>());
private boolean ingested = false;
private boolean readyToIngest = false;
// task that will clean up the created database file if the wizard is cancelled before it finishes
private AddImageAction.CleanupTask cleanupTask;
private final AddImageAction addImageAction;
private final AddImageWizardAddingProgressPanel progressPanel;
private final AddImageWizardChooseDataSourcePanel dataSourcePanel;
private DataSourceProcessor dsProcessor;
AddImageWizardIngestConfigPanel(AddImageWizardChooseDataSourcePanel dsPanel, AddImageAction action, AddImageWizardAddingProgressPanel proPanel) {
this.addImageAction = action;
this.progressPanel = proPanel;
this.dataSourcePanel = dsPanel;
/*
* Get the ingest job settings for the add data source wizard context
* and use them to create an ingest module configuration panel.
*/
IngestJobSettings ingestJobSettings = new IngestJobSettings(AddImageWizardIngestConfigPanel.class.getCanonicalName());
showIngestModuleConfigurationWarnings(ingestJobSettings);
ingestJobSettingsPanel = new IngestJobSettingsPanel(ingestJobSettings);
/*
* This flag is used to stop the data source processing thread from
* starting the ingest job before the user has finished configuring the
* ingest modules. It is only set in the EDT.
*/
ingestModulesConfigured = false;
/*
* This flag is required because because the storeSettings method is
* currently called twice during the course of executing the add data
* source wizard, whether invoked from the new case wizard or
* independently. This means that the tryStartDataSourceIngestJob method
* gets called three times: once when the data source processor
* completes, and twice when the two storeSettings calls are made.
*
* TODO (AUT-1864): Figure out whether storeSettings is always called
* twice by NetBeans, or the extra call is due to an Autopsy bug.
*/
ingestJobStarted = false;
showWarnings(ingestJobSettings);
this.ingestJobSettingsPanel = new IngestJobSettingsPanel(ingestJobSettings);
}
/**
* Gets the visual component for the panel. In this template, the component
* Get the visual component for the panel. In this template, the component
* is kept separate. This can be more efficient: if the wizard is created
* but never displayed, or not all panels are displayed, it is better to
* create only those which really need to be visible.
*
* @return The UI component of this wizard panel.
* @return component the UI component of this wizard panel
*/
@Override
public Component getComponent() {
if (null == component) {
if (component == null) {
component = new AddImageWizardIngestConfigVisual(this.ingestJobSettingsPanel);
}
return component;
}
/**
* Gets the help for this panel. When the panel is active, this is used as
* the help for the wizard dialog.
* Help for this panel. When the panel is active, this is used as the help
* for the wizard dialog.
*
* @return The help for this panel
* @return HelpCtx.DEFAULT_HELP the help for this panel
*/
@Override
public HelpCtx getHelp() {
// Show no Help button for this panel:
return HelpCtx.DEFAULT_HELP;
// If you have context help:
// return new HelpCtx(SampleWizardPanel1.class);
}
/**
* Tests whether or not the panel is finished. If the panel is valid, the
* "Finish" button will be enabled.
* Tests whether the panel is finished. If the panel is valid, the "Finish"
* button will be enabled.
*
* @return True or false.
* @return true the finish button should be always enabled at this point
*/
@Override
public boolean isValid() {
@ -153,53 +123,52 @@ final class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<Wi
// return someCondition();
// and when this condition changes (last form field filled in...) then:
// fireChangeEvent();
// and uncomment the complicated stuff below.
}
/**
* @inheritDoc
* Adds a listener to changes of the panel's validity.
*
* @param l the change listener to add
*/
@Override
public final void addChangeListener(ChangeListener listener) {
changeSupport.addChangeListener(listener);
public final void addChangeListener(ChangeListener l) {
}
/**
* @inheritDoc
* Removes a listener to changes of the panel's validity.
*
* @param l the change listener to move
*/
@Override
public final void removeChangeListener(ChangeListener listener) {
changeSupport.removeChangeListener(listener);
}
/**
* @inheritDoc
*/
protected final void fireChangeEvent() {
changeSupport.fireChange();
public final void removeChangeListener(ChangeListener l) {
}
// You can use a settings object to keep track of state. Normally the
// settings object will be the WizardDescriptor, so you can use
// WizardDescriptor.getProperty & putProperty to store information entered
// by the user.
/**
* Provides the wizard panel with the current data--either the default data
* or already-modified settings, if the user used the previous and/or next
* buttons. This method can be called multiple times on one instance of
* WizardDescriptor.Panel.
*
* @param settings The settings.
* @param settings the setting to be read from
*/
@Override
public void readSettings(WizardDescriptor settings) {
/*
* The user has pushed the next button on the previous panel of the add
* data source wizard. Start the data source processor so it can run
* while the user is doing the ingest module configuration. It is ok to
* do this now because the back button is disabled for this wizard - the
* user cannot go back to choose a different data source.
*
* RC: Not sure why the cancel button is disabled.
*/
JButton cancel = new JButton(NbBundle.getMessage(this.getClass(), "AddImageWizardIngestConfigPanel.CANCEL_BUTTON.text"));
JButton cancel = new JButton(
NbBundle.getMessage(this.getClass(), "AddImageWizardIngestConfigPanel.CANCEL_BUTTON.text"));
cancel.setEnabled(false);
settings.setOptions(new Object[]{WizardDescriptor.PREVIOUS_OPTION, WizardDescriptor.NEXT_OPTION, WizardDescriptor.FINISH_OPTION, cancel});
cleanupTask = null;
readyToIngest = false;
newContents.clear();
// Start processing the data source by handing it off to the selected DSP,
// so it gets going in the background while the user is still picking the Ingest modules
startDataSourceProcessing(settings);
}
@ -214,29 +183,16 @@ final class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<Wi
*/
@Override
public void storeSettings(WizardDescriptor settings) {
/*
* The user has pushed the next button on this panel. Save the ingest
* job settings for the add data source wizard context and try to start
* the ingest job. It is ok to do this now because the back button is
* disabled for this wizard - the user cannot go back to choose a
* different data source. However, the job will not be started if either
* the data source processor has not finished yet, or it finished but
* did not produce any Content objects for the data source.
*/
IngestJobSettings ingestJobSettings = this.ingestJobSettingsPanel.getSettings();
ingestJobSettings.save();
showIngestModuleConfigurationWarnings(ingestJobSettings);
ingestModulesConfigured = true;
tryStartIngestJob();
showWarnings(ingestJobSettings);
// Start ingest if it hasn't already been started
readyToIngest = true;
startIngest();
}
/**
* Displays any warnings returned form operations on the ingest job settings
* for the add data source wizard context.
*
* @param ingestJobSettings The ingest job settings.
*/
private static void showIngestModuleConfigurationWarnings(IngestJobSettings ingestJobSettings) {
private static void showWarnings(IngestJobSettings ingestJobSettings) {
List<String> warnings = ingestJobSettings.getWarnings();
if (warnings.isEmpty() == false) {
StringBuilder warningMessage = new StringBuilder();
@ -248,78 +204,76 @@ final class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<Wi
}
/**
* Starts the data source processor selected by the user when the previous
* panel was displayed.
* Start ingest after verifying we have a new image, we are ready to ingest,
* and we haven't already ingested.
*/
private void startIngest() {
if (!newContents.isEmpty() && readyToIngest && !ingested) {
ingested = true;
IngestManager.getInstance().queueIngestJob(newContents, ingestJobSettingsPanel.getSettings());
progressPanel.setStateFinished();
}
}
/**
* Starts the Data source processing by kicking off the selected
* DataSourceProcessor
*/
private void startDataSourceProcessing(WizardDescriptor settings) {
/*
* Create a unique id to use to synch up the data source events that are
* published for the data source being added.
*/
final UUID addDataSourceEventId = UUID.randomUUID();
final UUID dataSourceId = UUID.randomUUID();
/*
* Register a clean up task with the action that invokes the add data
* source wizard. This action takes responsibility for doing cleanup
* after the wizard is closed (see the definition of the AddImageAction
* class).
*/
cleanupTask = CallableSystemAction.get(AddImageAction.class).new CleanupTask() {
// Add a cleanup task to interrupt the background process if the
// wizard exits while the background process is running.
cleanupTask = addImageAction.new CleanupTask() {
@Override
void cleanup() throws Exception {
new Thread(() -> {
/*
* Publish a failed adding data source event, using the
* event id associated with the adding data source event.
*/
Case.getCurrentCase().notifyFailedAddingDataSource(addDataSourceEventId);
}).start();
dsProcessor.cancel();
cancelDataSourceProcessing(dataSourceId);
}
};
cleanupTask.enable();
/*
* Publish an adding data source event.
*/
// get the selected DSProcessor
dsProcessor = dataSourcePanel.getComponent().getCurrentDSProcessor();
new Thread(() -> {
Case.getCurrentCase().notifyAddingDataSource(addDataSourceEventId);
Case.getCurrentCase().notifyAddingDataSource(dataSourceId);
}).start();
/*
* Notify the progress panel for this wizard that data source processing
* is starting.
*/
progressPanel.setStateStarted();
/*
* Get the data source processor the user selected and start it.
*/
dsProcessor = selectDataSourcePanel.getComponent().getCurrentDSProcessor();
DataSourceProcessorCallback callback = new DataSourceProcessorCallback() {
DataSourceProcessorCallback cbObj = new DataSourceProcessorCallback() {
@Override
public void doneEDT(DataSourceProcessorCallback.DataSourceProcessorResult result, List<String> errList, List<Content> contents) {
dataSourceProcessorDone(addDataSourceEventId, result, errList, contents);
dataSourceProcessorDone(dataSourceId, result, errList, contents);
}
};
dsProcessor.run(progressPanel.getDSPProgressMonitor(), callback);
progressPanel.setStateStarted();
// Kick off the DSProcessor
dsProcessor.run(progressPanel.getDSPProgressMonitorImpl(), cbObj);
}
/*
* The callback for the data source processor to invoke when it finishes.
* Cancels the data source processing - in case the users presses 'Cancel'
*/
private void dataSourceProcessorDone(UUID addDataSourceEventId, DataSourceProcessorCallback.DataSourceProcessorResult result, List<String> errList, List<Content> contents) {
/*
* Disable the clean up task.
*/
private void cancelDataSourceProcessing(UUID dataSourceId) {
new Thread(() -> {
Case.getCurrentCase().notifyFailedAddingDataSource(dataSourceId);
}).start();
dsProcessor.cancel();
}
/*
* Callback for the data source processor. Invoked by the DSP on the EDT
* thread, when it finishes processing the data source.
*/
private void dataSourceProcessorDone(UUID dataSourceId, DataSourceProcessorCallback.DataSourceProcessorResult result, List<String> errList, List<Content> contents) {
// disable the cleanup task
cleanupTask.disable();
/*
* Get the user's attention.
*
* RC: Is this really necessary?
*/
java.awt.Toolkit.getDefaultToolkit().beep();
// Get attention for the process finish
java.awt.Toolkit.getDefaultToolkit().beep(); //BEEP!
AddImageWizardAddingProgressVisual panel = progressPanel.getComponent();
if (panel != null) {
Window w = SwingUtilities.getWindowAncestor(panel);
@ -327,12 +281,10 @@ final class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<Wi
w.toFront();
}
}
/*
* Notify the progress panel that the data source processor has finished
* its work and display the processing results on the progress panel.
*/
// Tell the panel we're done
progressPanel.setStateFinished();
//check the result and display to user
if (result == DataSourceProcessorCallback.DataSourceProcessorResult.NO_ERRORS) {
progressPanel.getComponent().setProgressBarTextAndColor(
NbBundle.getMessage(this.getClass(), "AddImageWizardIngestConfigPanel.dsProcDone.noErrs.text"), 100, Color.black);
@ -340,45 +292,32 @@ final class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<Wi
progressPanel.getComponent().setProgressBarTextAndColor(
NbBundle.getMessage(this.getClass(), "AddImageWizardIngestConfigPanel.dsProcDone.errs.text"), 100, Color.red);
}
//if errors, display them on the progress panel
boolean critErr = false;
if (result == DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS) {
critErr = true;
}
for (String err : errList) {
progressPanel.displayDataSourceProcessorError(err, critErr);
// TBD: there probably should be an error level for each error
progressPanel.addErrors(err, critErr);
}
/*
* Save the Content objects returned by the data source processor.
*/
newContents.clear();
newContents.addAll(contents);
//notify the UI of the new content added to the case
new Thread(() -> {
if (!newContents.isEmpty()) {
Case.getCurrentCase().notifyDataSourceAdded(newContents.get(0), addDataSourceEventId);
Case.getCurrentCase().notifyDataSourceAdded(newContents.get(0), dataSourceId);
} else {
Case.getCurrentCase().notifyFailedAddingDataSource(addDataSourceEventId);
Case.getCurrentCase().notifyFailedAddingDataSource(dataSourceId);
}
}).start();
/*
* Try starting the ingest job for this data source. If the data source
* processor finished before the user finished configuring the ingest
* modules, the job will not be started yet.
*/
tryStartIngestJob();
}
// Start ingest if we can
progressPanel.setStateStarted();
startIngest();
/**
* Starts an ingest job for the data source, but only if the data source
* processor has been run and has produced content, and the ingest modules
* are configured.
*/
synchronized private void tryStartIngestJob() {
if (!newContents.isEmpty() && ingestModulesConfigured && !ingestJobStarted) {
ingestJobStarted = true; // See contructor for comment on this flag.
IngestManager.getInstance().queueIngestJob(newContents, ingestJobSettingsPanel.getSettings());
}
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -28,52 +28,52 @@ import org.openide.WizardDescriptor;
import org.openide.util.NbBundle;
/**
* The iterator for the add data source wizard panels.
* The iterator class for the "Add Image" wizard panel. This class is used to
* iterate on the sequence of panels of the "Add Image" wizard panel.
*/
final class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescriptor> {
class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescriptor> {
private int index = 0;
private List<WizardDescriptor.Panel<WizardDescriptor>> panels;
private AddImageAction action;
AddImageWizardIterator(AddImageAction action) {
this.action = action;
}
/**
* Lazily create the panels for the add data source wizard.
* Initialize panels representing individual wizard's steps and sets various
* properties for them influencing wizard appearance.
*/
private List<WizardDescriptor.Panel<WizardDescriptor>> getPanels() {
if (null == panels) {
panels = new ArrayList<>();
if (panels == null) {
panels = new ArrayList<WizardDescriptor.Panel<WizardDescriptor>>();
/*
* Create the wizard panels. The first panel is used to select a
* data source. The second panel is used to configure the ingest
* modules. The third panel has a progress bar that tracks progress
* as the Sleuthkit layer adds the data source to the case database.
*/
AddImageWizardChooseDataSourcePanel dsPanel = new AddImageWizardChooseDataSourcePanel();
AddImageWizardAddingProgressPanel progressPanel = new AddImageWizardAddingProgressPanel();
AddImageWizardIngestConfigPanel ingestConfigPanel = new AddImageWizardIngestConfigPanel(dsPanel, progressPanel);
AddImageWizardChooseDataSourcePanel dsPanel = new AddImageWizardChooseDataSourcePanel(progressPanel);
AddImageWizardIngestConfigPanel ingestConfigPanel = new AddImageWizardIngestConfigPanel(dsPanel, action, progressPanel);
panels.add(dsPanel);
panels.add(ingestConfigPanel);
panels.add(progressPanel);
/*
* Set the appearance of the visual components of the panels.
*/
String[] steps = new String[panels.size()];
for (int i = 0; i < panels.size(); i++) {
Component visualComponent = panels.get(i).getComponent();
// Default step name to component name.
steps[i] = visualComponent.getName();
if (visualComponent instanceof JComponent) {
JComponent jc = (JComponent) visualComponent;
// Set step number.
jc.putClientProperty("WizardPanel_contentSelectedIndex", i);
// Sets step name.
Component c = panels.get(i).getComponent();
// Default step name to component name of panel.
steps[i] = c.getName();
if (c instanceof JComponent) { // assume Swing components
JComponent jc = (JComponent) c;
// Sets step number of a component
jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i));
// Sets steps names for a panel
jc.putClientProperty("WizardPanel_contentData", steps);
// Turn on subtitle creation.
// Turn on subtitle creation on each step
jc.putClientProperty("WizardPanel_autoWizardStyle", Boolean.TRUE);
// Show steps on the left side, with image in the background.
// Show steps on the left side with the image on the background
jc.putClientProperty("WizardPanel_contentDisplayed", Boolean.TRUE);
// Turn on step numbering.
// Turn on numbering of all steps
jc.putClientProperty("WizardPanel_contentNumbered", Boolean.TRUE);
}
}
@ -81,10 +81,20 @@ final class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDe
return panels;
}
/**
* Returns the index of the current panel. Note: 0 = panel 1, 1 = panel 2,
* etc
*
* @return index the current panel index
*/
public int getIndex() {
return index;
}
/**
* Gets the current panel.
*
* @return The current panel.
* @return panel the current panel
*/
@Override
public WizardDescriptor.Panel<WizardDescriptor> current() {
@ -98,17 +108,18 @@ final class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDe
/**
* Gets the name of the current panel.
*
* @return The name of the current panel.
* @return name the name of the current panel
*/
@Override
public String name() {
return NbBundle.getMessage(this.getClass(), "AddImageWizardIterator.stepXofN", Integer.toString(index + 1), getPanels().size());
return NbBundle.getMessage(this.getClass(), "AddImageWizardIterator.stepXofN", Integer.toString(index + 1),
getPanels().size());
}
/**
* Tests whether there is a next panel.
*
* @return True or false.
* @return boolean true if it has next panel, false if not
*/
@Override
public boolean hasNext() {
@ -118,18 +129,17 @@ final class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDe
/**
* Tests whether there is a previous panel.
*
* @return True or false.
* @return boolean true if it has previous panel, false if not
*/
@Override
// disable the previous button on all panels
public boolean hasPrevious() {
/*
* Disable the back buttons for the add data source wizard.
*/
return false;
}
/**
* Moves to the next panel.
* Moves to the next panel. I.e. increment its index, need not actually
* change any GUI itself.
*/
@Override
public void nextPanel() {
@ -140,7 +150,8 @@ final class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDe
}
/**
* Moves to the previous panel.
* Moves to the previous panel. I.e. decrement its index, need not actually
* change any GUI itself.
*/
@Override
public void previousPanel() {
@ -153,18 +164,12 @@ final class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDe
index--;
}
/**
* @inheritDoc
*/
// If nothing unusual changes in the middle of the wizard, simply:
@Override
public void addChangeListener(ChangeListener l) {
}
/**
* @inheritDoc
*/
@Override
public void removeChangeListener(ChangeListener l) {
}
}

View File

@ -93,6 +93,7 @@ AddImageAction.ingestConfig.ongoingIngest.msg=<html>Ingest is ongoing on another
AddImageAction.ingestConfig.ongoingIngest.title=Ingest in progress
AddImageTask.run.progress.adding=Adding\: {0}
AddImageTask.interrupt.exception.msg=Error stopping add-image process.
AddImageWizardAddingProgressPanel.isValid.focusNext=Next >
AddImageWizardAddingProgressPanel.stateStarted.progressBarText=*This process may take some time for large data sources.
AddImageWizardAddingProgressVisual.addingDsComplete.text=Adding Data Source - Complete
AddImageWizardAddingProgressVisual.getName.text=Add Data Source

View File

@ -88,6 +88,7 @@ AddImageAction.ingestConfig.ongoingIngest.msg=<html>\u4ed6\u306e\u30c7\u30fc\u30
AddImageAction.ingestConfig.ongoingIngest.title=\u51e6\u7406\u4e2d
AddImageTask.run.progress.adding=\u8ffd\u52a0\u4e2d\uff1a{0}
AddImageTask.interrupt.exception.msg=\u30a4\u30e1\u30fc\u30b8\u8ffd\u52a0\u30d7\u30ed\u30bb\u30b9\u306e\u505c\u6b62\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002
AddImageWizardAddingProgressPanel.isValid.focusNext=\u6b21 >
AddImageWizardAddingProgressPanel.stateStarted.progressBarText=*\u5927\u304d\u3044\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u5834\u5408\u3001\u3053\u306e\u30d7\u30ed\u30bb\u30b9\u306f\u6642\u9593\u304c\u304b\u304b\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002
AddImageWizardAddingProgressVisual.addingDsComplete.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u8ffd\u52a0 - \u5b8c\u4e86
AddImageWizardAddingProgressVisual.getName.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u8ffd\u52a0