diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java index c32cf6f87f..81143091d4 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java @@ -43,7 +43,7 @@ import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.Version; -import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; /** * The action associated with the Case/Open Case menu item via the layer.xml @@ -65,7 +65,7 @@ public final class CaseOpenAction extends CallableSystemAction implements Action private static final Logger LOGGER = Logger.getLogger(CaseOpenAction.class.getName()); private final FileFilter caseMetadataFileFilter; - private final JFileChooserHelper fileChooserHelper; + private final JFileChooserFactory fileChooserHelper; /** * Constructs the action associated with the Case/Open Case menu item via @@ -75,7 +75,7 @@ public final class CaseOpenAction extends CallableSystemAction implements Action */ public CaseOpenAction() { caseMetadataFileFilter = new FileNameExtensionFilter(NbBundle.getMessage(CaseOpenAction.class, "CaseOpenAction.autFilter.title", Version.getName(), CaseMetadata.getFileExtension()), CaseMetadata.getFileExtension().substring(1)); - fileChooserHelper = JFileChooserHelper.getHelper(); + fileChooserHelper = new JFileChooserFactory(); } /** diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java index 9f2a313ae3..20770a2c00 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java @@ -35,7 +35,7 @@ import org.sleuthkit.autopsy.coreutils.DriveUtils; import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.PathValidator; import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; -import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; import org.sleuthkit.datamodel.HashUtility; /** @@ -49,7 +49,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener { private static final long serialVersionUID = 1L; private static final String PROP_LASTIMAGE_PATH = "LBL_LastImage_PATH"; //NON-NLS private static final String[] SECTOR_SIZE_CHOICES = {"Auto Detect", "512", "1024", "2048", "4096"}; - private final JFileChooserHelper fileChooserHelper = JFileChooserHelper.getHelper(); + private final JFileChooserFactory fileChooserHelper = new JFileChooserFactory(); private JFileChooser fileChooser; private final String contextName; private final List fileChooserFilters; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java index 60f3bd4156..4759ce1177 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java @@ -32,7 +32,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; -import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; import org.sleuthkit.autopsy.imagewriter.ImageWriterSettings; /** @@ -60,7 +60,7 @@ final class LocalDiskPanel extends JPanel { private LocalDisk localDisk; private boolean enableNext = false; private JFileChooser fc; - private final JFileChooserHelper chooserHelper; + private final JFileChooserFactory chooserHelper; /** * Creates new form LocalDiskPanel @@ -70,7 +70,7 @@ final class LocalDiskPanel extends JPanel { customInit(); createTimeZoneList(); createSectorSizeList(); - chooserHelper = JFileChooserHelper.getHelper(); + chooserHelper = new JFileChooserFactory(); } /** diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java index 2e4f772baf..ffcbc7792f 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java @@ -32,7 +32,7 @@ import org.openide.util.NbBundle; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.coreutils.DriveUtils; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; @@ -47,7 +47,7 @@ class MissingImageDialog extends javax.swing.JDialog { SleuthkitCase db; private JFileChooser fileChooser; - private final JFileChooserHelper chooserHelper; + private final JFileChooserFactory chooserHelper; /** * Instantiate a MissingImageDialog. @@ -61,7 +61,7 @@ class MissingImageDialog extends javax.swing.JDialog { this.db = db; initComponents(); - chooserHelper = JFileChooserHelper.getHelper(); + chooserHelper = new JFileChooserFactory(); selectButton.setEnabled(false); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseVisualPanel1.java b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseVisualPanel1.java index bb518a92df..aa0ec43316 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseVisualPanel1.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseVisualPanel1.java @@ -30,7 +30,7 @@ import javax.swing.event.DocumentListener; import org.sleuthkit.autopsy.casemodule.Case.CaseType; import org.sleuthkit.autopsy.coreutils.PathValidator; import org.sleuthkit.autopsy.coreutils.PlatformUtil; -import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; /** * The JPanel for the first page of the new case wizard. @@ -38,7 +38,7 @@ import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives final class NewCaseVisualPanel1 extends JPanel implements DocumentListener { - private final JFileChooserHelper fileChooserHelper = JFileChooserHelper.getHelper(); + private final JFileChooserFactory fileChooserHelper = new JFileChooserFactory(); private final NewCaseWizardPanel1 wizPanel; /** diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/PListViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/PListViewer.java index 3547c5d8b2..4d2aae6760 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/PListViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/PListViewer.java @@ -56,7 +56,7 @@ import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; import org.sleuthkit.datamodel.TskCoreException; import org.xml.sax.SAXException; @@ -77,7 +77,7 @@ class PListViewer extends javax.swing.JPanel implements FileTypeViewer, Explorer private NSObject rootDict; - private final JFileChooserHelper fileChooserHelper = JFileChooserHelper.getHelper(); + private final JFileChooserFactory fileChooserHelper = new JFileChooserFactory(); /** * Creates new form PListViewer diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java index b4e6fdcf05..61066c0137 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java @@ -49,7 +49,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.autopsy.coreutils.SQLiteTableReader; -import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; /** * A file content viewer for SQLite database files. @@ -76,7 +76,7 @@ class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { SwingWorker worker; - private final JFileChooserHelper chooserHelper = JFileChooserHelper.getHelper(); + private final JFileChooserFactory chooserHelper = new JFileChooserFactory(); /** * Constructs a file content viewer for SQLite database files. diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index 91413334cb..6470161459 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -55,7 +55,7 @@ import org.sleuthkit.autopsy.machinesettings.UserMachinePreferencesException; import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.Version; -import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; import org.sleuthkit.autopsy.machinesettings.UserMachinePreferences.TempDirChoice; import org.sleuthkit.autopsy.report.ReportBranding; @@ -97,9 +97,9 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private final ReportBranding reportBranding; private JFileChooser heapFileChooser; - private final JFileChooserHelper logoChooserHelper = JFileChooserHelper.getHelper(); - private final JFileChooserHelper heapChooserHelper = JFileChooserHelper.getHelper(); - private final JFileChooserHelper tempChooserHelper = JFileChooserHelper.getHelper(); + private final JFileChooserFactory logoChooserHelper = new JFileChooserFactory(); + private final JFileChooserFactory heapChooserHelper = new JFileChooserFactory(); + private final JFileChooserFactory tempChooserHelper = new JFileChooserFactory(); /** * Instantiate the Autopsy options panel. diff --git a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/RawDSInputPanel.java b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/RawDSInputPanel.java index 6646525997..80acf8a8a1 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/RawDSInputPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/RawDSInputPanel.java @@ -32,7 +32,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.PathValidator; import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; -import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; /** * Allows examiner to supply a raw data source. @@ -43,7 +43,7 @@ final class RawDSInputPanel extends JPanel implements DocumentListener { private static final long serialVersionUID = 1L; //default private final String PROP_LASTINPUT_PATH = "LBL_LastInputFile_PATH"; private JFileChooser fc; - private JFileChooserHelper chooserHelper = JFileChooserHelper.getHelper(); + private JFileChooserFactory chooserHelper = new JFileChooserFactory(); // Externally supplied name is used to store settings private final String contextName; /** diff --git a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/xry/XRYDataSourceProcessorConfigPanel.java b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/xry/XRYDataSourceProcessorConfigPanel.java index 898e4cdef4..88c2c34bf3 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/xry/XRYDataSourceProcessorConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/xry/XRYDataSourceProcessorConfigPanel.java @@ -30,7 +30,7 @@ import javax.swing.JPanel; import org.apache.commons.lang3.StringUtils; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.coreutils.ModuleSettings; -import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; /** * Allows an examiner to configure the XRY Data source processor. @@ -50,7 +50,7 @@ final class XRYDataSourceProcessorConfigPanel extends JPanel { //panel will indicate when it is ready for an update. private final PropertyChangeSupport pcs; - private final JFileChooserHelper chooserHelper = JFileChooserHelper.getHelper(); + private final JFileChooserFactory chooserHelper = new JFileChooserFactory(); /** * Creates new form XRYDataSourceConfigPanel. diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/AddExternalViewerRulePanel.java b/Core/src/org/sleuthkit/autopsy/directorytree/AddExternalViewerRulePanel.java index 34e1c24a3d..473270811e 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/AddExternalViewerRulePanel.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/AddExternalViewerRulePanel.java @@ -26,7 +26,7 @@ import javax.swing.event.DocumentListener; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.GeneralFilter; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; /** @@ -38,7 +38,7 @@ class AddExternalViewerRulePanel extends javax.swing.JPanel { private static final Logger logger = Logger.getLogger(AddExternalViewerRulePanel.class.getName()); private static final long serialVersionUID = 1L; private JFileChooser fc; - private final JFileChooserHelper chooserHelper = JFileChooserHelper.getHelper(); + private final JFileChooserFactory chooserHelper = new JFileChooserFactory(); private static final GeneralFilter exeFilter = new GeneralFilter(GeneralFilter.EXECUTABLE_EXTS, GeneralFilter.EXECUTABLE_DESC); enum EVENT { diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExportCSVAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExportCSVAction.java index 904b423343..e1c95361e5 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExportCSVAction.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExportCSVAction.java @@ -51,7 +51,7 @@ import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFileProp import org.openide.nodes.Node; import org.openide.nodes.Node.PropertySet; import org.openide.nodes.Node.Property; -import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; /** * Exports CSV version of result nodes to a location selected by the user. @@ -70,7 +70,7 @@ public final class ExportCSVAction extends AbstractAction { // node in the array returns a reference to the same action object from Node.getActions(boolean). private static ExportCSVAction instance; - private static final JFileChooserHelper chooserHelper = JFileChooserHelper.getHelper(); + private static final JFileChooserFactory chooserHelper = new JFileChooserFactory(); /** * Get an instance of the Action. See above for why diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java index 4af306e58d..b13a149fc6 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java @@ -33,7 +33,7 @@ import org.netbeans.spi.options.OptionsPanelController; import org.sleuthkit.autopsy.casemodule.GeneralFilter; import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.PlatformUtil; -import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; /** * An options panel for the user to create, edit, and delete associations for @@ -47,7 +47,7 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme private ExternalViewerGlobalSettingsTableModel tableModel; - private final JFileChooserHelper chooserHelper = JFileChooserHelper.getHelper(); + private final JFileChooserFactory chooserHelper = new JFileChooserFactory(); ExternalViewerGlobalSettingsPanel() { this(new ExternalViewerGlobalSettingsTableModel(new String[] { diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExtractUnallocAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExtractUnallocAction.java index dcb55e5655..8b9f5af58d 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExtractUnallocAction.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExtractUnallocAction.java @@ -33,9 +33,6 @@ import java.util.List; import java.util.Set; import java.util.HashSet; import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.FutureTask; import java.util.logging.Level; import javax.swing.AbstractAction; import javax.swing.JFileChooser; @@ -50,6 +47,7 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; import org.sleuthkit.datamodel.AbstractContent; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; @@ -78,9 +76,7 @@ final class ExtractUnallocAction extends AbstractAction { private final Volume volume; private final Image image; - private final FutureTask futureFileChooser = new FutureTask<>(CustomFileChooser::new); - - private JFileChooser fileChooser = null; + private final JFileChooserFactory chooserFactory; /** * Create an instance of ExtractUnallocAction with a volume. @@ -90,7 +86,7 @@ final class ExtractUnallocAction extends AbstractAction { */ ExtractUnallocAction(String title, Volume volume) { this(title, null, volume); - + } /** @@ -110,9 +106,8 @@ final class ExtractUnallocAction extends AbstractAction { this.volume = null; this.image = image; - - ExecutorService executor = Executors.newSingleThreadExecutor(); - executor.execute(futureFileChooser); + + chooserFactory = new JFileChooserFactory(CustomFileChooser.class); } /** @@ -138,13 +133,7 @@ final class ExtractUnallocAction extends AbstractAction { return; } - if (fileChooser == null) { - try { - fileChooser = futureFileChooser.get(); - } catch (InterruptedException | ExecutionException ex) { - fileChooser = new CustomFileChooser(); - } - } + JFileChooser fileChooser = chooserFactory.getChooser(); fileChooser.setCurrentDirectory(new File(getExportDirectory(openCase))); if (JFileChooser.APPROVE_OPTION != fileChooser.showSaveDialog((Component) event.getSource())) { @@ -753,11 +742,11 @@ final class ExtractUnallocAction extends AbstractAction { } // A Custome JFileChooser for this Action Class. - private class CustomFileChooser extends JFileChooser { + public static class CustomFileChooser extends JFileChooser { private static final long serialVersionUID = 1L; - CustomFileChooser() { + public CustomFileChooser() { initalize(); } diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/actionhelpers/ExtractActionHelper.java b/Core/src/org/sleuthkit/autopsy/directorytree/actionhelpers/ExtractActionHelper.java index 3ef6a79f21..1a9ae807f5 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/actionhelpers/ExtractActionHelper.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/actionhelpers/ExtractActionHelper.java @@ -42,7 +42,7 @@ import org.sleuthkit.autopsy.coreutils.FileUtil; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.datamodel.ContentUtils; -import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; import org.sleuthkit.datamodel.AbstractFile; /** @@ -53,8 +53,8 @@ public class ExtractActionHelper { private final Logger logger = Logger.getLogger(ExtractActionHelper.class.getName()); private String userDefinedExportPath; - private final JFileChooserHelper extractFileHelper = JFileChooserHelper.getHelper(); - private final JFileChooserHelper extractFilesHelper = JFileChooserHelper.getHelper(); + private final JFileChooserFactory extractFileHelper = new JFileChooserFactory(); + private final JFileChooserFactory extractFilesHelper = new JFileChooserFactory(); /** * Extract the specified collection of files with an event specified for diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationSettingsPanel.java index 3e97344db5..a7cab0fd25 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationSettingsPanel.java @@ -35,7 +35,7 @@ import org.sleuthkit.autopsy.casemodule.GeneralFilter; import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.corecomponents.OptionsPanel; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; /** * A panel to allow the user to set the custom properties of the geolocation @@ -48,7 +48,7 @@ final class GeolocationSettingsPanel extends javax.swing.JPanel implements Optio private static final Logger logger = Logger.getLogger(GeolocationSettingsPanel.class.getName()); - private static final JFileChooserHelper chooserHelper = JFileChooserHelper.getHelper(); + private static final JFileChooserFactory chooserHelper = new JFileChooserFactory(); /** * Creates new GeolocationSettingsPanel diff --git a/Core/src/org/sleuthkit/autopsy/guicomponeontutils/JFileChooserFactory.java b/Core/src/org/sleuthkit/autopsy/guicomponeontutils/JFileChooserFactory.java new file mode 100755 index 0000000000..d885b3b8a6 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/guicomponeontutils/JFileChooserFactory.java @@ -0,0 +1,146 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.guicomponeontutils; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import java.awt.Cursor; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.FutureTask; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.JFileChooser; +import org.openide.windows.WindowManager; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; + +/** + * Factory class for initializing JFileChooser instances in a background thread. + * + * It is a known issue that on Windows a JFileChooser can take an indeterminate + * amount of time to initialize. Therefore when a JFileChooser is initialized on + * the EDT there is the potential for the UI to appear hung while initialization + * is occurring. + * + * Initializing a JFileChooser in a background thread should prevent the UI from + * hanging. Using this Factory class at component construction time should allow + * enough time for the JFileChooser to be initialized in the background before + * the UI user causes an event which will launch the JFileChooser. If the + * JFileChooser is not initialized prior to the event occurring, the EDT will be + * blocked , but the wait cursor will appear. + * + * https://stackoverflow.com/questions/49792375/jfilechooser-is-very-slow-when-using-windows-look-and-feel + */ +public final class JFileChooserFactory { + + private static final Logger logger = Logger.getLogger(JFileChooserFactory.class.getName()); + + private final FutureTask futureFileChooser; + private JFileChooser chooser; + + /** + * Create a new instance of the factory. The constructor will kick of an + * executor to that will execute the task of initializing the JFileChooser. + */ + public JFileChooserFactory() { + this(null); + } + + /** + * Create a new instance of the factory using a class that extends + * JFileChooser. The class default constructor will be called to initialize + * the class. + * + * The passed in Class must be public and its default constructor must be + * public. + * + * @param cls Class type to initialize. + */ + public JFileChooserFactory(Class cls) { + if (cls == null) { + futureFileChooser = new FutureTask<>(JFileChooser::new); + } else { + futureFileChooser = new FutureTask<>(new ChooserCallable(cls)); + } + + ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("JFileChooser-background-thread").build()); + executor.execute(futureFileChooser); + } + + /** + * Return and instance of JFileChooser to the caller. + * + * This call may block the EDT if the JFileChooser initialization has not + * completed. + * + * @return + */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + public JFileChooser getChooser() { + if (chooser == null) { + // In case this takes a moment show the wait cursor. + try { + WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + try { + // get() will only return when the initilization of the + // JFileChooser has completed. + chooser = futureFileChooser.get(); + } catch (InterruptedException | ExecutionException ex) { + // An exception is generally not expected. On the off chance + // one does occur save the sisutation by created a new + // instance in the EDT. + // If an exception does occur + logger.log(Level.WARNING, "Failed to initialize JFileChooser in background thread."); + chooser = new JFileChooser(); + } + } finally { + WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + } + + return chooser; + } + + /** + * Simple Callable that will initialize any subclass of JFileChooser using + * the default constructor. + * + * Note that the class and default constructor must be public for this to + * work properly. + */ + private class ChooserCallable implements Callable { + + private final Class type; + + /** + * Construct a new instance for the given class type. + * + * @param type Class type to initialize. + */ + ChooserCallable(Class type) { + this.type = type; + } + + @Override + public JFileChooser call() throws Exception { + return type.newInstance(); + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/guicomponeontutils/JFileChooserHelper.java b/Core/src/org/sleuthkit/autopsy/guicomponeontutils/JFileChooserHelper.java deleted file mode 100755 index 3d7cdb78b8..0000000000 --- a/Core/src/org/sleuthkit/autopsy/guicomponeontutils/JFileChooserHelper.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2021 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.guicomponeontutils; - -import java.awt.Cursor; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.FutureTask; -import javax.swing.JFileChooser; -import org.openide.windows.WindowManager; - -/** - * Helper class that will initialize JFileChooser instances in background threads. - * - * On windows JFileChooser can take a long time to initialize. This helper class - * takes the work of initializing the JFileChooser off of the EDT so that in - * theory the when the chooser is needed initialized and ready to be displayed - * to the user. - * - * https://stackoverflow.com/questions/49792375/jfilechooser-is-very-slow-when-using-windows-look-and-feel - */ -public final class JFileChooserHelper { - private final FutureTask futureFileChooser = new FutureTask<>(JFileChooser::new); - private JFileChooser chooser; - - /** - * Get a helper instance. - * - * @return - */ - public static JFileChooserHelper getHelper() { - return new JFileChooserHelper(); - } - - /** - * Create a new instance of the helper class. The constructor will - * kick of an executor to that will execute the task of initializing the - * JFileChooser. - */ - private JFileChooserHelper() { - ExecutorService executor = Executors.newSingleThreadExecutor(); - executor.execute(futureFileChooser); - } - - /** - * Return and instance of JFileChooser to the caller. - * - * This call may block the EDT if the JFileChooser initialization has not - * completed. - * - * @return - */ - public JFileChooser getChooser() { - if (chooser == null) { - // In case this takes a moment show the wait cursor. - WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - try { - // get() will only return when the initilization of the - // JFileChooser has completed. - chooser = futureFileChooser.get(); - } catch (InterruptedException | ExecutionException ex) { - // If an exception occured create a new instance of JFileChooser. - chooser = new JFileChooser(); - } - WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } - - return chooser; - } -} diff --git a/Core/src/org/sleuthkit/autopsy/healthmonitor/HealthMonitorDashboard.java b/Core/src/org/sleuthkit/autopsy/healthmonitor/HealthMonitorDashboard.java index f52c2aaf77..0b7e0b8364 100644 --- a/Core/src/org/sleuthkit/autopsy/healthmonitor/HealthMonitorDashboard.java +++ b/Core/src/org/sleuthkit/autopsy/healthmonitor/HealthMonitorDashboard.java @@ -61,7 +61,7 @@ import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil; -import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; /** * Dashboard for viewing metrics and controlling the health monitor. @@ -87,7 +87,7 @@ public class HealthMonitorDashboard { private JDialog dialog = null; private final Container parentWindow; - private final JFileChooserHelper chooserHelper; + private final JFileChooserFactory chooserHelper; /** * Create an instance of the dashboard. @@ -98,7 +98,7 @@ public class HealthMonitorDashboard { timingData = new HashMap<>(); userData = new ArrayList<>(); parentWindow = parent; - chooserHelper = JFileChooserHelper.getHelper(); + chooserHelper = new JFileChooserFactory(); } /** diff --git a/Core/src/org/sleuthkit/autopsy/logicalimager/configuration/ConfigVisualPanel1.java b/Core/src/org/sleuthkit/autopsy/logicalimager/configuration/ConfigVisualPanel1.java index 7cc36dfad3..523a3693ce 100644 --- a/Core/src/org/sleuthkit/autopsy/logicalimager/configuration/ConfigVisualPanel1.java +++ b/Core/src/org/sleuthkit/autopsy/logicalimager/configuration/ConfigVisualPanel1.java @@ -50,7 +50,7 @@ import org.apache.commons.lang.StringUtils; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; import org.sleuthkit.autopsy.logicalimager.dsp.DriveListUtils; /** @@ -64,7 +64,7 @@ final class ConfigVisualPanel1 extends JPanel { private static final String DEFAULT_CONFIG_FILE_NAME = "logical-imager-config.json"; private static final String UPDATE_UI_EVENT_NAME = "UPDATE_UI"; private String configFilename; - private final JFileChooserHelper chooserHelper; + private final JFileChooserFactory chooserHelper; /** * Creates new form ConfigVisualPanel1 @@ -76,7 +76,7 @@ final class ConfigVisualPanel1 extends JPanel { refreshDriveList(); updateControls(); }); - chooserHelper = JFileChooserHelper.getHelper(); + chooserHelper = new JFileChooserFactory(); } @NbBundle.Messages({ diff --git a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/LogicalImagerPanel.java b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/LogicalImagerPanel.java index 7142e04781..e247a25f89 100644 --- a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/LogicalImagerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/LogicalImagerPanel.java @@ -44,7 +44,7 @@ import javax.swing.table.TableColumn; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; /** * Panel for adding an logical image file from drive letters. Allows the user to @@ -68,7 +68,7 @@ final class LogicalImagerPanel extends JPanel implements DocumentListener { private final Pattern regex = Pattern.compile("Logical_Imager_(.+)_(\\d{4})(\\d{2})(\\d{2})_(\\d{2})_(\\d{2})_(\\d{2})"); private Path manualImageDirPath; private DefaultTableModel imageTableModel; - private final JFileChooserHelper chooserHelper; + private final JFileChooserFactory chooserHelper; /** * Creates new form LogicalImagerPanel @@ -81,7 +81,7 @@ final class LogicalImagerPanel extends JPanel implements DocumentListener { configureImageTable(); jScrollPane1.setBorder(null); clearImageTable(); - chooserHelper = JFileChooserHelper.getHelper(); + chooserHelper = new JFileChooserFactory(); } /** diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java index d2252aff94..18dffede59 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java @@ -18,21 +18,15 @@ */ package org.sleuthkit.autopsy.modules.hashdatabase; -import java.awt.Cursor; import java.io.File; import java.io.IOException; import java.nio.file.Paths; import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.FutureTask; import java.util.logging.Level; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JOptionPane; import org.apache.commons.io.FilenameUtils; -import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; @@ -51,6 +45,7 @@ import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.featureaccess.FeatureAccessUtils; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; /** * Instances of this class allow a user to create a new hash database and add it @@ -69,7 +64,7 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { private CentralRepoOrganization selectedOrg = null; private List orgs = null; static final String HASH_DATABASE_DIR_NAME = "HashDatabases"; - private final FutureTask futureFileChooser = new FutureTask<>(CustomFileChooser::new); + private final JFileChooserFactory chooserFactory; /** * Displays a dialog that allows a user to create a new hash database and @@ -79,11 +74,10 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { HashDbCreateDatabaseDialog() { super((JFrame) WindowManager.getDefault().getMainWindow(), NbBundle.getMessage(HashDbCreateDatabaseDialog.class, "HashDbCreateDatabaseDialog.createHashDbMsg"), true); initComponents(); + chooserFactory = new JFileChooserFactory(CustomFileChooser.class); enableComponents(); display(); - ExecutorService executor = Executors.newSingleThreadExecutor(); - executor.execute(futureFileChooser); } /** @@ -147,7 +141,7 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { /** * Customize the JFileChooser. */ - private class CustomFileChooser extends JFileChooser { + public static class CustomFileChooser extends JFileChooser { private static final long serialVersionUID = 1L; @@ -448,17 +442,11 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { path.append(".").append(HashDbManager.getHashDatabaseFileExtension()); if(fileChooser == null) { - setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - try { - fileChooser = futureFileChooser.get(); - } catch (InterruptedException | ExecutionException ex) { - fileChooser = new CustomFileChooser(); - } + fileChooser = chooserFactory.getChooser(); fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); fileChooser.setDragEnabled(false); fileChooser.setMultiSelectionEnabled(false); - setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java index 55051cd3f0..9e9156dd62 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java @@ -43,7 +43,7 @@ import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDbManagerExc import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.featureaccess.FeatureAccessUtils; -import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; /** * Instances of this class allow a user to select an existing hash database and @@ -59,7 +59,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { private final static String LAST_FILE_PATH_KEY = "HashDbImport_Path"; private CentralRepoOrganization selectedOrg = null; private List orgs = null; - private final JFileChooserHelper chooserHelper; + private final JFileChooserFactory chooserHelper; /** * Displays a dialog that allows a user to select an existing hash database @@ -70,7 +70,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { super((JFrame) WindowManager.getDefault().getMainWindow(), NbBundle.getMessage(HashDbImportDatabaseDialog.class, "HashDbImportDatabaseDialog.importHashDbMsg"), true); - chooserHelper = JFileChooserHelper.getHelper(); + chooserHelper = new JFileChooserFactory(); initComponents(); enableComponents(); display(); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index 1ff46b95c8..18fe932d45 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -65,7 +65,7 @@ import org.sleuthkit.datamodel.SleuthkitJNI; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; -import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType; /** @@ -95,7 +95,7 @@ public class HashDbManager implements PropertyChangeListener { private static final String KNOWN_STATUS_PARAM = "knownStatus"; private static final Pattern OFFICIAL_FILENAME = Pattern.compile("(?<" + DB_NAME_PARAM + ">.+?)\\.(?<" + KNOWN_STATUS_PARAM + ">.+?)\\." + KDB_EXT); - private final JFileChooserHelper chooserHelper; + private final JFileChooserFactory chooserHelper; private static final FilenameFilter DEFAULT_KDB_FILTER = new FilenameFilter() { @Override @@ -139,7 +139,7 @@ public class HashDbManager implements PropertyChangeListener { } private HashDbManager() { - chooserHelper = JFileChooserHelper.getHelper(); + chooserHelper = new JFileChooserFactory(); loadHashsetsConfiguration(); } diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/stix/STIXReportModuleConfigPanel.java b/Core/src/org/sleuthkit/autopsy/report/modules/stix/STIXReportModuleConfigPanel.java index bb23320c87..a1161737ac 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/stix/STIXReportModuleConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/stix/STIXReportModuleConfigPanel.java @@ -20,7 +20,7 @@ package org.sleuthkit.autopsy.report.modules.stix; import java.io.File; import javax.swing.JFileChooser; -import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserHelper; +import org.sleuthkit.autopsy.guicomponeontutils.JFileChooserFactory; /** * Configuration panel for STIX report generation. @@ -30,7 +30,7 @@ public class STIXReportModuleConfigPanel extends javax.swing.JPanel { String stixFile = null; boolean showAllResults; - private final JFileChooserHelper chooserHelper; + private final JFileChooserFactory chooserHelper; /** * Creates new form STIXReportModuleConfigPanel @@ -39,7 +39,7 @@ public class STIXReportModuleConfigPanel extends javax.swing.JPanel { initComponents(); showAllResults = false; jCheckBox1.setSelected(false); - chooserHelper = JFileChooserHelper.getHelper(); + chooserHelper = new JFileChooserFactory(); } void setConfiguration(STIXReportModuleSettings settings) {