diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java index 0ba92c7bce..25789939b3 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2017 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -43,6 +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.guiutils.JFileChooserFactory; /** * The action associated with the Case/Open Case menu item via the layer.xml @@ -64,6 +65,8 @@ public final class CaseOpenAction extends CallableSystemAction implements Action private static final Logger LOGGER = Logger.getLogger(CaseOpenAction.class.getName()); private final FileFilter caseMetadataFileFilter; + private final JFileChooserFactory fileChooserHelper; + /** * Constructs the action associated with the Case/Open Case menu item via * the layer.xml file, a toolbar button, and the Open Case button of the @@ -72,6 +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 = new JFileChooserFactory(); } /** @@ -80,7 +84,7 @@ public final class CaseOpenAction extends CallableSystemAction implements Action * to open the case described by the file. */ void openCaseSelectionWindow() { - JFileChooser fileChooser = new JFileChooser(); + JFileChooser fileChooser = fileChooserHelper.getChooser(); fileChooser.setDragEnabled(false); fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); fileChooser.setMultiSelectionEnabled(false); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java index 4c6126fcb7..eda7149f66 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2018 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,6 +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.guiutils.JFileChooserFactory; import org.sleuthkit.datamodel.HashUtility; /** @@ -48,8 +49,10 @@ 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 JFileChooser fileChooser = new JFileChooser(); + private final JFileChooserFactory fileChooserHelper = new JFileChooserFactory(); + private JFileChooser fileChooser; private final String contextName; + private final List fileChooserFilters; /** * Creates new form ImageFilePanel @@ -73,14 +76,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener { sectorSizeComboBox.setSelectedIndex(0); errorLabel.setVisible(false); - - fileChooser.setDragEnabled(false); - fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); - fileChooser.setMultiSelectionEnabled(false); - fileChooserFilters.forEach(fileChooser::addChoosableFileFilter); - if (fileChooserFilters.isEmpty() == false) { - fileChooser.setFileFilter(fileChooserFilters.get(0)); - } + this.fileChooserFilters = fileChooserFilters; } /** @@ -132,6 +128,21 @@ public class ImageFilePanel extends JPanel implements DocumentListener { private JTextField getSha256TextField() { return sha256HashTextField; } + + private JFileChooser getChooser() { + if(fileChooser == null) { + fileChooser = fileChooserHelper.getChooser(); + fileChooser.setDragEnabled(false); + fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + fileChooser.setMultiSelectionEnabled(false); + fileChooserFilters.forEach(fileChooser::addChoosableFileFilter); + if (fileChooserFilters.isEmpty() == false) { + fileChooser.setFileFilter(fileChooserFilters.get(0)); + } + } + + return fileChooser; + } /** * This method is called from within the constructor to initialize the form. @@ -298,12 +309,13 @@ public class ImageFilePanel extends JPanel implements DocumentListener { String oldText = getContentPaths(); // set the current directory of the FileChooser if the ImagePath Field is valid File currentDir = new File(oldText); + JFileChooser chooser = getChooser(); if (currentDir.exists()) { - fileChooser.setCurrentDirectory(currentDir); + chooser.setCurrentDirectory(currentDir); } - if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { - String path = fileChooser.getSelectedFile().getPath(); + if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { + String path = chooser.getSelectedFile().getPath(); if (path.endsWith(".001")) { String zeroX3_path = StringUtils.removeEnd(path, ".001") + ".000"; if (new File(zeroX3_path).exists()) { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java index 469b93da66..b0031ed1c7 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2018 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,6 +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.guiutils.JFileChooserFactory; import org.sleuthkit.autopsy.imagewriter.ImageWriterSettings; /** @@ -58,7 +59,8 @@ final class LocalDiskPanel extends JPanel { private static final long serialVersionUID = 1L; private LocalDisk localDisk; private boolean enableNext = false; - private final JFileChooser fc = new JFileChooser(); + private JFileChooser fc; + private final JFileChooserFactory chooserHelper; /** * Creates new form LocalDiskPanel @@ -68,6 +70,7 @@ final class LocalDiskPanel extends JPanel { customInit(); createTimeZoneList(); createSectorSizeList(); + chooserHelper = new JFileChooserFactory(); } /** @@ -261,6 +264,7 @@ final class LocalDiskPanel extends JPanel { }//GEN-LAST:event_pathTextFieldKeyReleased private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed + fc = chooserHelper.getChooser(); String oldText = pathTextField.getText(); // set the current directory of the FileChooser if the ImagePath Field is valid File currentFile = new File(oldText); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java index 201d25ecef..e4edc6e7bb 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2012-2018 Basis Technology Corp. + * Copyright 2012-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,6 +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.guiutils.JFileChooserFactory; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; @@ -45,7 +46,8 @@ class MissingImageDialog extends javax.swing.JDialog { long obj_id; SleuthkitCase db; - private final JFileChooser fileChooser = new JFileChooser(); + private JFileChooser fileChooser; + private final JFileChooserFactory chooserHelper; /** * Instantiate a MissingImageDialog. @@ -58,17 +60,8 @@ class MissingImageDialog extends javax.swing.JDialog { this.obj_id = obj_id; this.db = db; initComponents(); - - fileChooser.setDragEnabled(false); - fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); - fileChooser.setMultiSelectionEnabled(false); - - List fileFiltersList = ImageDSProcessor.getFileFiltersList(); - for (FileFilter fileFilter : fileFiltersList) { - fileChooser.addChoosableFileFilter(fileFilter); - } - fileChooser.setFileFilter(fileFiltersList.get(0)); - + + chooserHelper = new JFileChooserFactory(); selectButton.setEnabled(false); } @@ -270,6 +263,19 @@ class MissingImageDialog extends javax.swing.JDialog { private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed + if(fileChooser == null) { + fileChooser = chooserHelper.getChooser(); + fileChooser.setDragEnabled(false); + fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + fileChooser.setMultiSelectionEnabled(false); + + List fileFiltersList = ImageDSProcessor.getFileFiltersList(); + for (FileFilter fileFilter : fileFiltersList) { + fileChooser.addChoosableFileFilter(fileFilter); + } + fileChooser.setFileFilter(fileFiltersList.get(0)); + } + String oldText = pathNameTextField.getText(); lbWarning.setText(""); // set the current directory of the FileChooser if the ImagePath Field is valid diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseVisualPanel1.java b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseVisualPanel1.java index 32812b56ce..64def92cc2 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseVisualPanel1.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseVisualPanel1.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2020 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,6 +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.guiutils.JFileChooserFactory; /** * The JPanel for the first page of the new case wizard. @@ -37,7 +38,7 @@ import org.sleuthkit.autopsy.coreutils.PlatformUtil; @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives final class NewCaseVisualPanel1 extends JPanel implements DocumentListener { - private final JFileChooser fileChooser = new JFileChooser(); + private final JFileChooserFactory fileChooserHelper = new JFileChooserFactory(); private final NewCaseWizardPanel1 wizPanel; /** @@ -353,8 +354,9 @@ final class NewCaseVisualPanel1 extends JPanel implements DocumentListener { * @param evt the action event */ private void caseDirBrowseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_caseDirBrowseButtonActionPerformed + JFileChooser fileChooser = fileChooserHelper.getChooser(); fileChooser.setDragEnabled(false); - if (!caseParentDirTextField.getText().trim().equals("")) { + if (!caseParentDirTextField.getText().trim().isEmpty()) { fileChooser.setCurrentDirectory(new File(caseParentDirTextField.getText())); } fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/UnpackagePortableCaseDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/UnpackagePortableCaseDialog.java index 3b86909953..94c708fdbb 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/UnpackagePortableCaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/UnpackagePortableCaseDialog.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/PListViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/PListViewer.java index f73cb6350f..51e9a549ee 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/PListViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/PListViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2018-2019 Basis Technology Corp. + * Copyright 2018-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -56,6 +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.guiutils.JFileChooserFactory; import org.sleuthkit.datamodel.TskCoreException; import org.xml.sax.SAXException; @@ -75,6 +76,8 @@ class PListViewer extends javax.swing.JPanel implements FileTypeViewer, Explorer private ExplorerManager explorerManager; private NSObject rootDict; + + private final JFileChooserFactory fileChooserHelper = new JFileChooserFactory(); /** * Creates new form PListViewer @@ -203,7 +206,7 @@ class PListViewer extends javax.swing.JPanel implements FileTypeViewer, Explorer return; } - final JFileChooser fileChooser = new JFileChooser(); + final JFileChooser fileChooser = fileChooserHelper.getChooser(); fileChooser.setCurrentDirectory(new File(openCase.getExportDirectory())); fileChooser.setFileFilter(new FileNameExtensionFilter("XML file", "xml")); diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java index 7772be7d29..38630b4aa4 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2018-2019 Basis Technology Corp. + * Copyright 2018-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -49,6 +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.guiutils.JFileChooserFactory; /** * A file content viewer for SQLite database files. @@ -74,6 +75,8 @@ class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { private int currPage = 0; // curr page of rows being displayed SwingWorker worker; + + private final JFileChooserFactory chooserHelper = new JFileChooserFactory(); /** * Constructs a file content viewer for SQLite database files. @@ -280,7 +283,7 @@ class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { private void exportCsvButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportCsvButtonActionPerformed Case openCase = Case.getCurrentCase(); File caseDirectory = new File(openCase.getExportDirectory()); - JFileChooser fileChooser = new JFileChooser(); + JFileChooser fileChooser = chooserHelper.getChooser(); fileChooser.setDragEnabled(false); fileChooser.setCurrentDirectory(caseDirectory); //Set a filter to let the filechooser only work for csv files diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index 56ff4a0993..0a52ae749c 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -55,6 +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.guiutils.JFileChooserFactory; import org.sleuthkit.autopsy.machinesettings.UserMachinePreferences.TempDirChoice; import org.sleuthkit.autopsy.report.ReportBranding; @@ -82,8 +83,8 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; private static final String DEFAULT_HEAP_DUMP_FILE_FIELD = ""; - private final JFileChooser logoFileChooser; - private final JFileChooser tempDirChooser; + private JFileChooser logoFileChooser; + private JFileChooser tempDirChooser; private static final String ETC_FOLDER_NAME = "etc"; private static final String CONFIG_FILE_EXTENSION = ".conf"; private static final long ONE_BILLION = 1000000000L; //used to roughly convert system memory from bytes to gigabytes @@ -94,27 +95,17 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private String initialMemValue = Long.toString(Runtime.getRuntime().maxMemory() / ONE_BILLION); private final ReportBranding reportBranding; - private final JFileChooser heapFileChooser; + private JFileChooser heapFileChooser; + + private final JFileChooserFactory logoChooserHelper = new JFileChooserFactory(); + private final JFileChooserFactory heapChooserHelper = new JFileChooserFactory(); + private final JFileChooserFactory tempChooserHelper = new JFileChooserFactory(); /** * Instantiate the Autopsy options panel. */ AutopsyOptionsPanel() { initComponents(); - logoFileChooser = new JFileChooser(); - logoFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); - logoFileChooser.setMultiSelectionEnabled(false); - logoFileChooser.setAcceptAllFileFilterUsed(false); - logoFileChooser.setFileFilter(new GeneralFilter(GeneralFilter.GRAPHIC_IMAGE_EXTS, GeneralFilter.GRAPHIC_IMG_DECR)); - - tempDirChooser = new JFileChooser(); - tempDirChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - tempDirChooser.setMultiSelectionEnabled(false); - - heapFileChooser = new JFileChooser(); - heapFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - heapFileChooser.setMultiSelectionEnabled(false); - if (!isJVMHeapSettingsCapable()) { //32 bit JVM has a max heap size of 1.4 gb to 4 gb depending on OS //So disabling the setting of heap size when the JVM is not 64 bit @@ -1242,6 +1233,11 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { "# {0} - path", "AutopsyOptionsPanel_tempDirectoryBrowseButtonActionPerformed_onInvalidPath_description=Unable to create temporary directory within specified path: {0}",}) private void tempDirectoryBrowseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tempDirectoryBrowseButtonActionPerformed + if(tempDirChooser == null) { + tempDirChooser = tempChooserHelper.getChooser(); + tempDirChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + tempDirChooser.setMultiSelectionEnabled(false); + } int returnState = tempDirChooser.showOpenDialog(this); if (returnState == JFileChooser.APPROVE_OPTION) { String specifiedPath = tempDirChooser.getSelectedFile().getPath(); @@ -1318,6 +1314,13 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { }//GEN-LAST:event_defaultLogoRBActionPerformed private void browseLogosButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseLogosButtonActionPerformed + if(logoFileChooser == null) { + logoFileChooser = logoChooserHelper.getChooser(); + logoFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + logoFileChooser.setMultiSelectionEnabled(false); + logoFileChooser.setAcceptAllFileFilterUsed(false); + logoFileChooser.setFileFilter(new GeneralFilter(GeneralFilter.GRAPHIC_IMAGE_EXTS, GeneralFilter.GRAPHIC_IMG_DECR)); + } String oldLogoPath = agencyLogoPathField.getText(); int returnState = logoFileChooser.showOpenDialog(this); if (returnState == JFileChooser.APPROVE_OPTION) { @@ -1360,6 +1363,11 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { "AutopsyOptionsPanel_heapDumpBrowseButtonActionPerformed_fileAlreadyExistsMessage=File already exists. Please select a new location." }) private void heapDumpBrowseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_heapDumpBrowseButtonActionPerformed + if(heapFileChooser == null) { + heapFileChooser = heapChooserHelper.getChooser(); + heapFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + heapFileChooser.setMultiSelectionEnabled(false); + } String oldHeapPath = heapDumpFileField.getText(); if (!StringUtils.isBlank(oldHeapPath)) { heapFileChooser.setCurrentDirectory(new File(oldHeapPath)); diff --git a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/RawDSInputPanel.java b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/RawDSInputPanel.java index 1a02f65060..dbb571d4ba 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/RawDSInputPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/RawDSInputPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2018 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,6 +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.guiutils.JFileChooserFactory; /** * Allows examiner to supply a raw data source. @@ -41,7 +42,8 @@ final class RawDSInputPanel extends JPanel implements DocumentListener { private static final long TWO_GB = 2000000000L; private static final long serialVersionUID = 1L; //default private final String PROP_LASTINPUT_PATH = "LBL_LastInputFile_PATH"; - private final JFileChooser fc = new JFileChooser(); + private JFileChooser fc; + private JFileChooserFactory chooserHelper = new JFileChooserFactory(); // Externally supplied name is used to store settings private final String contextName; /** @@ -51,11 +53,6 @@ final class RawDSInputPanel extends JPanel implements DocumentListener { initComponents(); errorLabel.setVisible(false); - - fc.setDragEnabled(false); - fc.setFileSelectionMode(JFileChooser.FILES_ONLY); - fc.setMultiSelectionEnabled(false); - this.contextName = context; } @@ -200,18 +197,25 @@ final class RawDSInputPanel extends JPanel implements DocumentListener { }// //GEN-END:initComponents @SuppressWarnings("deprecation") private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed - String oldText = pathTextField.getText(); - // set the current directory of the FileChooser if the ImagePath Field is valid - File currentDir = new File(oldText); - if (currentDir.exists()) { - fc.setCurrentDirectory(currentDir); - } + if (fc == null) { + fc = chooserHelper.getChooser(); + fc.setDragEnabled(false); + fc.setFileSelectionMode(JFileChooser.FILES_ONLY); + fc.setMultiSelectionEnabled(false); + } - int retval = fc.showOpenDialog(this); - if (retval == JFileChooser.APPROVE_OPTION) { - String path = fc.getSelectedFile().getPath(); - pathTextField.setText(path); - } + String oldText = pathTextField.getText(); + // set the current directory of the FileChooser if the ImagePath Field is valid + File currentDir = new File(oldText); + if (currentDir.exists()) { + fc.setCurrentDirectory(currentDir); + } + + int retval = fc.showOpenDialog(this); + if (retval == JFileChooser.APPROVE_OPTION) { + String path = fc.getSelectedFile().getPath(); + pathTextField.setText(path); + } }//GEN-LAST:event_browseButtonActionPerformed private void j2GBBreakupRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_j2GBBreakupRadioButtonActionPerformed diff --git a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/xry/XRYDataSourceProcessorConfigPanel.java b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/xry/XRYDataSourceProcessorConfigPanel.java index a641ea1f73..d7a78ea389 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/xry/XRYDataSourceProcessorConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/xry/XRYDataSourceProcessorConfigPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,6 +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.guiutils.JFileChooserFactory; /** * Allows an examiner to configure the XRY Data source processor. @@ -49,6 +50,8 @@ final class XRYDataSourceProcessorConfigPanel extends JPanel { //panel will indicate when it is ready for an update. private final PropertyChangeSupport pcs; + private final JFileChooserFactory chooserHelper = new JFileChooserFactory(); + /** * Creates new form XRYDataSourceConfigPanel. * Prevent direct instantiation. @@ -191,7 +194,7 @@ final class XRYDataSourceProcessorConfigPanel extends JPanel { * report folder. */ private void fileBrowserButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fileBrowserButtonActionPerformed - JFileChooser fileChooser = new JFileChooser(); + JFileChooser fileChooser = chooserHelper.getChooser(); fileChooser.setMultiSelectionEnabled(false); fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); Optional lastUsedPath = getLastUsedPath(); diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/AddExternalViewerRulePanel.java b/Core/src/org/sleuthkit/autopsy/directorytree/AddExternalViewerRulePanel.java index 3cf1d2445a..beafb6ef5d 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/AddExternalViewerRulePanel.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/AddExternalViewerRulePanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2018 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,6 +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.guiutils.JFileChooserFactory; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; /** @@ -35,7 +36,9 @@ import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; class AddExternalViewerRulePanel extends javax.swing.JPanel { private static final Logger logger = Logger.getLogger(AddExternalViewerRulePanel.class.getName()); - private final JFileChooser fc = new JFileChooser(); + private static final long serialVersionUID = 1L; + private JFileChooser fc; + private final JFileChooserFactory chooserHelper = new JFileChooserFactory(); private static final GeneralFilter exeFilter = new GeneralFilter(GeneralFilter.EXECUTABLE_EXTS, GeneralFilter.EXECUTABLE_DESC); enum EVENT { @@ -47,10 +50,6 @@ class AddExternalViewerRulePanel extends javax.swing.JPanel { */ AddExternalViewerRulePanel() { initComponents(); - fc.setDragEnabled(false); - fc.setFileSelectionMode(JFileChooser.FILES_ONLY); - fc.setMultiSelectionEnabled(false); - fc.setFileFilter(exeFilter); customize(); } @@ -260,6 +259,13 @@ class AddExternalViewerRulePanel extends javax.swing.JPanel { }// //GEN-END:initComponents private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed + if(fc == null) { + fc = chooserHelper.getChooser(); + fc.setDragEnabled(false); + fc.setFileSelectionMode(JFileChooser.FILES_ONLY); + fc.setMultiSelectionEnabled(false); + fc.setFileFilter(exeFilter); + } int returnState = fc.showOpenDialog(this); if (returnState == JFileChooser.APPROVE_OPTION) { String path = fc.getSelectedFile().getPath(); diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExportCSVAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExportCSVAction.java index 7b312211c4..27b7a11a84 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExportCSVAction.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExportCSVAction.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -51,6 +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.guiutils.JFileChooserFactory; /** * Exports CSV version of result nodes to a location selected by the user. @@ -68,6 +69,8 @@ public final class ExportCSVAction extends AbstractAction { // org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every // node in the array returns a reference to the same action object from Node.getActions(boolean). private static ExportCSVAction instance; + + private static final JFileChooserFactory chooserHelper = new JFileChooserFactory(); /** * Get an instance of the Action. See above for why @@ -125,7 +128,7 @@ public final class ExportCSVAction extends AbstractAction { // Set up the file chooser with a default name and either the Export // folder or the last used folder. String fileName = getDefaultOutputFileName(nodesToExport.iterator().next().getParentNode()); - JFileChooser fileChooser = new JFileChooser(); + JFileChooser fileChooser = chooserHelper.getChooser(); fileChooser.setCurrentDirectory(new File(getExportDirectory(Case.getCurrentCaseThrows()))); fileChooser.setSelectedFile(new File(fileName)); fileChooser.setFileFilter(new FileNameExtensionFilter("csv file", "csv")); diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java index 0cfbd7d5e5..0235c849bd 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2018 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,6 +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.guiutils.JFileChooserFactory; /** * An options panel for the user to create, edit, and delete associations for @@ -42,9 +43,13 @@ import org.sleuthkit.autopsy.coreutils.PlatformUtil; @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel implements OptionsPanel { - private ExternalViewerGlobalSettingsTableModel tableModel; + private static final long serialVersionUID = 1L; - public ExternalViewerGlobalSettingsPanel() { + private ExternalViewerGlobalSettingsTableModel tableModel; + + private final JFileChooserFactory chooserHelper = new JFileChooserFactory(); + + ExternalViewerGlobalSettingsPanel() { this(new ExternalViewerGlobalSettingsTableModel(new String[] { "Mime type/Extension", "Application"})); } @@ -52,7 +57,7 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme /** * Creates new form ExternalViewerGlobalSettingsPanel */ - public ExternalViewerGlobalSettingsPanel(ExternalViewerGlobalSettingsTableModel tableModel) { + ExternalViewerGlobalSettingsPanel(ExternalViewerGlobalSettingsTableModel tableModel) { initComponents(); this.tableModel = tableModel; customizeComponents(tableModel); @@ -335,7 +340,7 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme }//GEN-LAST:event_deleteRuleButtonActionPerformed private void browseHxDDirectoryActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseHxDDirectoryActionPerformed - JFileChooser fileWindow = new JFileChooser(); + JFileChooser fileWindow = chooserHelper.getChooser(); fileWindow.setFileSelectionMode(JFileChooser.FILES_ONLY); GeneralFilter exeFilter = new GeneralFilter(GeneralFilter.EXECUTABLE_EXTS, GeneralFilter.EXECUTABLE_DESC); File HxDPathFile = new File(HxDPath.getText()); diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExtractUnallocAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExtractUnallocAction.java index dcb55e5655..a29f5c39ef 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.guiutils.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 5bdec7daa6..5a28bd9c12 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/actionhelpers/ExtractActionHelper.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/actionhelpers/ExtractActionHelper.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2019 Basis Technology Corp. + * Copyright 2013-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -42,6 +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.guiutils.JFileChooserFactory; import org.sleuthkit.datamodel.AbstractFile; /** @@ -51,6 +52,9 @@ public class ExtractActionHelper { private final Logger logger = Logger.getLogger(ExtractActionHelper.class.getName()); private String userDefinedExportPath; + + private final JFileChooserFactory extractFileHelper = new JFileChooserFactory(); + private final JFileChooserFactory extractFilesHelper = new JFileChooserFactory(); /** * Extract the specified collection of files with an event specified for @@ -89,7 +93,7 @@ public class ExtractActionHelper { logger.log(Level.INFO, "Exception while getting open case.", ex); //NON-NLS return; } - JFileChooser fileChooser = new JFileChooser(); + JFileChooser fileChooser = extractFileHelper.getChooser(); fileChooser.setCurrentDirectory(new File(getExportDirectory(openCase))); // If there is an attribute name, change the ":". Otherwise the extracted file will be hidden fileChooser.setSelectedFile(new File(FileUtil.escapeFileName(selectedFile.getName()))); @@ -117,7 +121,7 @@ public class ExtractActionHelper { logger.log(Level.INFO, "Exception while getting open case.", ex); //NON-NLS return; } - JFileChooser folderChooser = new JFileChooser(); + JFileChooser folderChooser = extractFilesHelper.getChooser(); folderChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); folderChooser.setCurrentDirectory(new File(getExportDirectory(openCase))); if (folderChooser.showSaveDialog((Component) event.getSource()) == JFileChooser.APPROVE_OPTION) { diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationSettingsPanel.java index 6043ff1a46..de33c0ca2b 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationSettingsPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,6 +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.guiutils.JFileChooserFactory; /** * A panel to allow the user to set the custom properties of the geolocation @@ -46,6 +47,8 @@ final class GeolocationSettingsPanel extends javax.swing.JPanel implements Optio private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(GeolocationSettingsPanel.class.getName()); + + private static final JFileChooserFactory chooserHelper = new JFileChooserFactory(); /** * Creates new GeolocationSettingsPanel @@ -313,7 +316,7 @@ final class GeolocationSettingsPanel extends javax.swing.JPanel implements Optio }// //GEN-END:initComponents private void zipFileBrowseBntActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_zipFileBrowseBntActionPerformed - JFileChooser fileWindow = new JFileChooser(); + JFileChooser fileWindow = chooserHelper.getChooser(); fileWindow.setFileSelectionMode(JFileChooser.FILES_ONLY); GeneralFilter fileFilter = new GeneralFilter(Arrays.asList(".zip"), "Zips (*.zip)"); //NON-NLS fileWindow.setDragEnabled(false); @@ -374,7 +377,7 @@ final class GeolocationSettingsPanel extends javax.swing.JPanel implements Optio }//GEN-LAST:event_mbtilesRBtnActionPerformed private void mbtilesBrowseBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mbtilesBrowseBtnActionPerformed - JFileChooser fileWindow = new JFileChooser(); + JFileChooser fileWindow = chooserHelper.getChooser(); fileWindow.setFileSelectionMode(JFileChooser.FILES_ONLY); GeneralFilter fileFilter = new GeneralFilter(Arrays.asList(".mbtiles"), "MBTiles (*.mbtiles)"); //NON-NLS fileWindow.setDragEnabled(false); diff --git a/Core/src/org/sleuthkit/autopsy/guiutils/JFileChooserFactory.java b/Core/src/org/sleuthkit/autopsy/guiutils/JFileChooserFactory.java new file mode 100755 index 0000000000..85e7936882 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/guiutils/JFileChooserFactory.java @@ -0,0 +1,147 @@ +/* + * 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.guiutils; + +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; + private final ExecutorService executor; + + /** + * Create a new instance of the factory. The constructor will kick off an + * executor to execute the initializing the JFileChooser task. + */ + 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)); + } + + 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 situation by created a new + // instance in the EDT. + logger.log(Level.WARNING, "Failed to initialize JFileChooser in background thread."); + chooser = new JFileChooser(); + } + } finally { + WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + executor.shutdown(); + } + } + + 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/healthmonitor/HealthMonitorDashboard.java b/Core/src/org/sleuthkit/autopsy/healthmonitor/HealthMonitorDashboard.java index 81fbd99d69..bc673144c8 100644 --- a/Core/src/org/sleuthkit/autopsy/healthmonitor/HealthMonitorDashboard.java +++ b/Core/src/org/sleuthkit/autopsy/healthmonitor/HealthMonitorDashboard.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2018 Basis Technology Corp. + * Copyright 2018-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -61,6 +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.guiutils.JFileChooserFactory; /** * Dashboard for viewing metrics and controlling the health monitor. @@ -86,6 +87,8 @@ public class HealthMonitorDashboard { private JDialog dialog = null; private final Container parentWindow; + private final JFileChooserFactory chooserHelper; + /** * Create an instance of the dashboard. * Call display() after creation to show the dashboard. @@ -95,6 +98,7 @@ public class HealthMonitorDashboard { timingData = new HashMap<>(); userData = new ArrayList<>(); parentWindow = parent; + chooserHelper = new JFileChooserFactory(); } /** @@ -495,7 +499,7 @@ public class HealthMonitorDashboard { reportButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { - JFileChooser reportFileChooser = new JFileChooser(); + JFileChooser reportFileChooser = chooserHelper.getChooser(); reportFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); reportFileChooser.setCurrentDirectory(new File(UserPreferences.getHealthMonitorReportPath())); final DateFormat csvTimestampFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); diff --git a/Core/src/org/sleuthkit/autopsy/logicalimager/configuration/ConfigVisualPanel1.java b/Core/src/org/sleuthkit/autopsy/logicalimager/configuration/ConfigVisualPanel1.java index a5fdfd3bfc..688c5e72a3 100644 --- a/Core/src/org/sleuthkit/autopsy/logicalimager/configuration/ConfigVisualPanel1.java +++ b/Core/src/org/sleuthkit/autopsy/logicalimager/configuration/ConfigVisualPanel1.java @@ -1,7 +1,7 @@ /* * Autopsy * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -50,6 +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.guiutils.JFileChooserFactory; import org.sleuthkit.autopsy.logicalimager.dsp.DriveListUtils; /** @@ -63,6 +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 JFileChooserFactory chooserHelper; /** * Creates new form ConfigVisualPanel1 @@ -74,6 +76,7 @@ final class ConfigVisualPanel1 extends JPanel { refreshDriveList(); updateControls(); }); + chooserHelper = new JFileChooserFactory(); } @NbBundle.Messages({ @@ -332,7 +335,7 @@ final class ConfigVisualPanel1 extends JPanel { "ConfigVisualPanel1.configurationError=Configuration error",}) private void chooseFile(String title) { final String jsonExt = ".json"; // NON-NLS - JFileChooser fileChooser = new JFileChooser(); + JFileChooser fileChooser = chooserHelper.getChooser(); fileChooser.setDialogTitle(title); fileChooser.setDragEnabled(false); fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); diff --git a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/LogicalImagerPanel.java b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/LogicalImagerPanel.java index 6a1198ea63..cc6297ae15 100644 --- a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/LogicalImagerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/LogicalImagerPanel.java @@ -1,7 +1,7 @@ /* * Autopsy * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -44,6 +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.guiutils.JFileChooserFactory; /** * Panel for adding an logical image file from drive letters. Allows the user to @@ -64,10 +65,10 @@ final class LogicalImagerPanel extends JPanel implements DocumentListener { private static final int NUMBER_OF_VISIBLE_COLUMNS = 2; private static final String[] EMPTY_LIST_DATA = {}; - private final JFileChooser fileChooser = new JFileChooser(); 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 JFileChooserFactory chooserHelper; /** * Creates new form LogicalImagerPanel @@ -80,6 +81,7 @@ final class LogicalImagerPanel extends JPanel implements DocumentListener { configureImageTable(); jScrollPane1.setBorder(null); clearImageTable(); + chooserHelper = new JFileChooserFactory(); } /** @@ -316,6 +318,7 @@ final class LogicalImagerPanel extends JPanel implements DocumentListener { "LogicalImagerPanel.messageLabel.directoryFormatInvalid=Directory {0} does not match format Logical_Imager_HOSTNAME_yyyymmdd_HH_MM_SS" }) private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed + JFileChooser fileChooser = chooserHelper.getChooser(); imageTable.clearSelection(); manualImageDirPath = null; setErrorMessage(NO_IMAGE_SELECTED); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java index 63a8c84e93..ee7634a276 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2020 Basis Technology Corp. + * Copyright 2013-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -45,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.guiutils.JFileChooserFactory; /** * Instances of this class allow a user to create a new hash database and add it @@ -56,12 +57,14 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { private static final String DEFAULT_FILE_NAME = NbBundle .getMessage(HashDbCreateDatabaseDialog.class, "HashDbCreateDatabaseDialog.defaultFileName"); + private static final long serialVersionUID = 1L; private JFileChooser fileChooser = null; private HashDb newHashDb = null; private final static String LAST_FILE_PATH_KEY = "HashDbCreate_Path"; private CentralRepoOrganization selectedOrg = null; private List orgs = null; static final String HASH_DATABASE_DIR_NAME = "HashDatabases"; + private final JFileChooserFactory chooserFactory; /** * Displays a dialog that allows a user to create a new hash database and @@ -70,10 +73,11 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { */ HashDbCreateDatabaseDialog() { super((JFrame) WindowManager.getDefault().getMainWindow(), NbBundle.getMessage(HashDbCreateDatabaseDialog.class, "HashDbCreateDatabaseDialog.createHashDbMsg"), true); - initFileChooser(); initComponents(); + chooserFactory = new JFileChooserFactory(CustomFileChooser.class); enableComponents(); display(); + } /** @@ -84,43 +88,7 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { HashDb getHashDatabase() { return newHashDb; } - - private void initFileChooser() { - fileChooser = new JFileChooser() { - @Override - public void approveSelection() { - File selectedFile = getSelectedFile(); - if (!FilenameUtils.getExtension(selectedFile.getName()).equalsIgnoreCase(HashDbManager.getHashDatabaseFileExtension())) { - if (JOptionPane.showConfirmDialog(this, - NbBundle.getMessage(this.getClass(), - "HashDbCreateDatabaseDialog.hashDbMustHaveFileExtensionMsg", - HashDbManager.getHashDatabaseFileExtension()), - NbBundle.getMessage(this.getClass(), - "HashDbCreateDatabaseDialog.fileNameErr"), - JOptionPane.OK_CANCEL_OPTION) == JOptionPane.CANCEL_OPTION) { - cancelSelection(); - } - return; - } - if (selectedFile.exists()) { - if (JOptionPane.showConfirmDialog(this, - NbBundle.getMessage(this.getClass(), - "HashDbCreateDatabaseDialog.fileNameAlreadyExistsMsg"), - NbBundle.getMessage(this.getClass(), - "HashDbCreateDatabaseDialog.fileExistsErr"), - JOptionPane.OK_CANCEL_OPTION) == JOptionPane.CANCEL_OPTION) { - cancelSelection(); - } - return; - } - super.approveSelection(); - } - }; - fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); - fileChooser.setDragEnabled(false); - fileChooser.setMultiSelectionEnabled(false); - } - + private void display() { setLocationRelativeTo(getOwner()); setVisible(true); @@ -169,6 +137,43 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Failure loading organizations", ex); } } + + /** + * Customize the JFileChooser. + */ + public static class CustomFileChooser extends JFileChooser { + + private static final long serialVersionUID = 1L; + + @Override + public void approveSelection() { + File selectedFile = getSelectedFile(); + if (!FilenameUtils.getExtension(selectedFile.getName()).equalsIgnoreCase(HashDbManager.getHashDatabaseFileExtension())) { + if (JOptionPane.showConfirmDialog(this, + NbBundle.getMessage(this.getClass(), + "HashDbCreateDatabaseDialog.hashDbMustHaveFileExtensionMsg", + HashDbManager.getHashDatabaseFileExtension()), + NbBundle.getMessage(this.getClass(), + "HashDbCreateDatabaseDialog.fileNameErr"), + JOptionPane.OK_CANCEL_OPTION) == JOptionPane.CANCEL_OPTION) { + cancelSelection(); + } + return; + } + if (selectedFile.exists()) { + if (JOptionPane.showConfirmDialog(this, + NbBundle.getMessage(this.getClass(), + "HashDbCreateDatabaseDialog.fileNameAlreadyExistsMsg"), + NbBundle.getMessage(this.getClass(), + "HashDbCreateDatabaseDialog.fileExistsErr"), + JOptionPane.OK_CANCEL_OPTION) == JOptionPane.CANCEL_OPTION) { + cancelSelection(); + } + return; + } + super.approveSelection(); + } + } /** * This method is called from within the constructor to initialize the form. @@ -435,6 +440,16 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { path.append(File.separator).append(DEFAULT_FILE_NAME); } path.append(".").append(HashDbManager.getHashDatabaseFileExtension()); + + if(fileChooser == null) { + fileChooser = chooserFactory.getChooser(); + + fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + fileChooser.setDragEnabled(false); + fileChooser.setMultiSelectionEnabled(false); + } + + fileChooser.setSelectedFile(new File(path.toString())); if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) { File databaseFile = fileChooser.getSelectedFile(); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java index c854cb165d..6f4d2606d7 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2020 Basis Technology Corp. + * Copyright 2013-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -43,6 +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.guiutils.JFileChooserFactory; /** * Instances of this class allow a user to select an existing hash database and @@ -52,12 +53,13 @@ import org.sleuthkit.autopsy.featureaccess.FeatureAccessUtils; @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives final class HashDbImportDatabaseDialog extends javax.swing.JDialog { - private final JFileChooser fileChooser; + private JFileChooser fileChooser; private String selectedFilePath = ""; private HashDb selectedHashDb = null; private final static String LAST_FILE_PATH_KEY = "HashDbImport_Path"; private CentralRepoOrganization selectedOrg = null; private List orgs = null; + private final JFileChooserFactory chooserHelper; /** * Displays a dialog that allows a user to select an existing hash database @@ -68,10 +70,9 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { super((JFrame) WindowManager.getDefault().getMainWindow(), NbBundle.getMessage(HashDbImportDatabaseDialog.class, "HashDbImportDatabaseDialog.importHashDbMsg"), true); - this.fileChooser = new JFileChooser(); + chooserHelper = new JFileChooserFactory(); initComponents(); enableComponents(); - initFileChooser(); display(); } @@ -84,16 +85,6 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { return selectedHashDb; } - private void initFileChooser() { - fileChooser.setDragEnabled(false); - fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); - String[] EXTENSION = new String[]{"txt", "kdb", "idx", "hash", "Hash", "hsh"}; //NON-NLS - FileNameExtensionFilter filter = new FileNameExtensionFilter( - NbBundle.getMessage(this.getClass(), "HashDbImportDatabaseDialog.fileNameExtFilter.text"), EXTENSION); - fileChooser.setFileFilter(filter); - fileChooser.setMultiSelectionEnabled(false); - } - private void display() { setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); setVisible(true); @@ -421,6 +412,17 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { }// //GEN-END:initComponents private void openButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openButtonActionPerformed + if(fileChooser == null) { + fileChooser = chooserHelper.getChooser(); + fileChooser.setDragEnabled(false); + fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + String[] EXTENSION = new String[]{"txt", "kdb", "idx", "hash", "Hash", "hsh"}; //NON-NLS + FileNameExtensionFilter filter = new FileNameExtensionFilter( + NbBundle.getMessage(this.getClass(), "HashDbImportDatabaseDialog.fileNameExtFilter.text"), EXTENSION); + fileChooser.setFileFilter(filter); + fileChooser.setMultiSelectionEnabled(false); + } + String lastBaseDirectory = Paths.get(PlatformUtil.getUserConfigDirectory(), HashDbCreateDatabaseDialog.HASH_DATABASE_DIR_NAME).toString(); if (ModuleSettings.settingExists(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY)) { lastBaseDirectory = ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index 40544c5485..cf099075ed 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2018 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -65,6 +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.guiutils.JFileChooserFactory; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType; /** @@ -93,6 +94,8 @@ public class HashDbManager implements PropertyChangeListener { private static final String DB_NAME_PARAM = "dbName"; 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 JFileChooserFactory chooserHelper; private static final FilenameFilter DEFAULT_KDB_FILTER = new FilenameFilter() { @Override @@ -136,6 +139,7 @@ public class HashDbManager implements PropertyChangeListener { } private HashDbManager() { + chooserHelper = new JFileChooserFactory(); loadHashsetsConfiguration(); } @@ -870,7 +874,7 @@ public class HashDbManager implements PropertyChangeListener { private String searchForFile() { String filePath = null; - JFileChooser fc = new JFileChooser(); + JFileChooser fc = chooserHelper.getChooser(); fc.setDragEnabled(false); fc.setFileSelectionMode(JFileChooser.FILES_ONLY); String[] EXTENSION = new String[]{"txt", "idx", "hash", "Hash", "kdb"}; //NON-NLS 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 5a7d5b9b35..e32d3a0d0d 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/stix/STIXReportModuleConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/stix/STIXReportModuleConfigPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2018 Basis Technology Corp. + * Copyright 2013-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.report.modules.stix; import java.io.File; import javax.swing.JFileChooser; +import org.sleuthkit.autopsy.guiutils.JFileChooserFactory; /** * Configuration panel for STIX report generation. @@ -29,6 +30,7 @@ public class STIXReportModuleConfigPanel extends javax.swing.JPanel { String stixFile = null; boolean showAllResults; + private final JFileChooserFactory chooserHelper; /** * Creates new form STIXReportModuleConfigPanel @@ -37,6 +39,7 @@ public class STIXReportModuleConfigPanel extends javax.swing.JPanel { initComponents(); showAllResults = false; jCheckBox1.setSelected(false); + chooserHelper = new JFileChooserFactory(); } void setConfiguration(STIXReportModuleSettings settings) { @@ -138,7 +141,7 @@ public class STIXReportModuleConfigPanel extends javax.swing.JPanel { private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed - JFileChooser fileChooser = new JFileChooser(); + JFileChooser fileChooser = chooserHelper.getChooser(); fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); File currentSelection = new File(jStixFileTextField.getText());