19 package org.sleuthkit.autopsy.logicalimager.dsp;
 
   21 import java.awt.Color;
 
   22 import java.awt.Component;
 
   24 import java.io.FilenameFilter;
 
   25 import java.io.IOException;
 
   26 import java.nio.file.FileStore;
 
   27 import java.nio.file.Files;
 
   28 import java.nio.file.Path;
 
   29 import java.nio.file.Paths;
 
   30 import java.util.ArrayList;
 
   31 import java.util.List;
 
   32 import java.util.logging.Level;
 
   33 import java.util.regex.Matcher;
 
   34 import java.util.regex.Pattern;
 
   35 import javax.swing.JFileChooser;
 
   36 import javax.swing.JPanel;
 
   37 import javax.swing.JTable;
 
   38 import javax.swing.ListSelectionModel;
 
   39 import javax.swing.event.DocumentEvent;
 
   40 import javax.swing.event.DocumentListener;
 
   41 import javax.swing.filechooser.FileSystemView;
 
   42 import javax.swing.table.DefaultTableModel;
 
   43 import javax.swing.table.TableColumn;
 
   44 import org.openide.util.NbBundle.Messages;
 
   54     "LogicalImagerPanel.messageLabel.noImageSelected=No image selected",
 
   55     "LogicalImagerPanel.messageLabel.driveHasNoImages=Drive has no images",
 
   56     "LogicalImagerPanel.selectAcquisitionFromDriveLabel.text=Select acquisition from Drive",})
 
   57 @SuppressWarnings(
"PMD.SingularField") 
 
   58 final class LogicalImagerPanel extends JPanel implements DocumentListener {
 
   60     private static final Logger logger = Logger.getLogger(LogicalImagerPanel.class.getName());
 
   61     private static final long serialVersionUID = 1L;
 
   62     private static final String NO_IMAGE_SELECTED = Bundle.LogicalImagerPanel_messageLabel_noImageSelected();
 
   63     private static final String DRIVE_HAS_NO_IMAGES = Bundle.LogicalImagerPanel_messageLabel_driveHasNoImages();
 
   64     private static final int COLUMN_TO_SORT_ON_INDEX = 1;
 
   65     private static final int NUMBER_OF_VISIBLE_COLUMNS = 2;
 
   66     private static final String[] EMPTY_LIST_DATA = {};
 
   68     private final Pattern regex = Pattern.compile(
"Logical_Imager_(.+)_(\\d{4})(\\d{2})(\\d{2})_(\\d{2})_(\\d{2})_(\\d{2})");
 
   69     private Path manualImageDirPath;
 
   70     private DefaultTableModel imageTableModel;
 
   71     private final JFileChooserFactory chooserHelper;
 
   79     private LogicalImagerPanel(String context) {
 
   81         configureImageTable();
 
   82         jScrollPane1.setBorder(null);
 
   84         chooserHelper = 
new JFileChooserFactory();
 
   91     private void configureImageTable() {
 
   93         if (imageTable.getColumnCount() > NUMBER_OF_VISIBLE_COLUMNS) {
 
   94             TableColumn columnToHide = imageTable.getColumn(imageTableModel.getColumnName(NUMBER_OF_VISIBLE_COLUMNS));
 
   95             if (columnToHide != null) {
 
   96                 imageTable.removeColumn(columnToHide);
 
   99             imageTable.getRowSorter().toggleSortOrder(COLUMN_TO_SORT_ON_INDEX);
 
  100             imageTable.getRowSorter().toggleSortOrder(COLUMN_TO_SORT_ON_INDEX);
 
  112     static synchronized LogicalImagerPanel createInstance(String context) {
 
  113         LogicalImagerPanel instance = 
new LogicalImagerPanel(context);
 
  115         instance.imageTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
 
  125     private void initComponents() {
 
  127         buttonGroup1 = 
new javax.swing.ButtonGroup();
 
  128         browseButton = 
new javax.swing.JButton();
 
  129         importRadioButton = 
new javax.swing.JRadioButton();
 
  130         manualRadioButton = 
new javax.swing.JRadioButton();
 
  131         pathTextField = 
new javax.swing.JTextField();
 
  132         selectFolderLabel = 
new javax.swing.JLabel();
 
  133         selectDriveLabel = 
new javax.swing.JLabel();
 
  134         selectFromDriveLabel = 
new javax.swing.JLabel();
 
  135         driveListScrollPane = 
new javax.swing.JScrollPane();
 
  136         driveList = 
new javax.swing.JList<>();
 
  137         refreshButton = 
new javax.swing.JButton();
 
  138         imageScrollPane = 
new javax.swing.JScrollPane();
 
  139         imageTable = 
new javax.swing.JTable();
 
  140         jSeparator2 = 
new javax.swing.JSeparator();
 
  141         jScrollPane1 = 
new javax.swing.JScrollPane();
 
  142         messageTextArea = 
new javax.swing.JTextArea();
 
  144         setMinimumSize(
new java.awt.Dimension(0, 65));
 
  145         setPreferredSize(
new java.awt.Dimension(403, 65));
 
  147         org.openide.awt.Mnemonics.setLocalizedText(browseButton, 
org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, 
"LogicalImagerPanel.browseButton.text")); 
 
  148         browseButton.setEnabled(
false);
 
  149         browseButton.addActionListener(
new java.awt.event.ActionListener() {
 
  150             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  151                 browseButtonActionPerformed(evt);
 
  155         buttonGroup1.add(importRadioButton);
 
  156         importRadioButton.setSelected(
true);
 
  157         org.openide.awt.Mnemonics.setLocalizedText(importRadioButton, 
org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, 
"LogicalImagerPanel.importRadioButton.text")); 
 
  158         importRadioButton.setToolTipText(
"");
 
  159         importRadioButton.addActionListener(
new java.awt.event.ActionListener() {
 
  160             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  161                 importRadioButtonActionPerformed(evt);
 
  165         buttonGroup1.add(manualRadioButton);
 
  166         org.openide.awt.Mnemonics.setLocalizedText(manualRadioButton, 
org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, 
"LogicalImagerPanel.manualRadioButton.text")); 
 
  167         manualRadioButton.addActionListener(
new java.awt.event.ActionListener() {
 
  168             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  169                 manualRadioButtonActionPerformed(evt);
 
  173         pathTextField.setDisabledTextColor(java.awt.Color.black);
 
  174         pathTextField.setEnabled(
false);
 
  176         org.openide.awt.Mnemonics.setLocalizedText(selectFolderLabel, 
org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, 
"LogicalImagerPanel.selectFolderLabel.text")); 
 
  178         org.openide.awt.Mnemonics.setLocalizedText(selectDriveLabel, 
org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, 
"LogicalImagerPanel.selectDriveLabel.text")); 
 
  180         org.openide.awt.Mnemonics.setLocalizedText(selectFromDriveLabel, 
org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, 
"LogicalImagerPanel.selectFromDriveLabel.text")); 
 
  182         driveList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
 
  183         driveList.addMouseListener(
new java.awt.event.MouseAdapter() {
 
  184             public void mouseReleased(java.awt.event.MouseEvent evt) {
 
  185                 driveListMouseReleased(evt);
 
  188         driveList.addKeyListener(
new java.awt.event.KeyAdapter() {
 
  189             public void keyReleased(java.awt.event.KeyEvent evt) {
 
  190                 driveListKeyReleased(evt);
 
  193         driveListScrollPane.setViewportView(driveList);
 
  195         org.openide.awt.Mnemonics.setLocalizedText(refreshButton, 
org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, 
"LogicalImagerPanel.refreshButton.text")); 
 
  196         refreshButton.addActionListener(
new java.awt.event.ActionListener() {
 
  197             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  198                 refreshButtonActionPerformed(evt);
 
  202         imageScrollPane.setPreferredSize(
new java.awt.Dimension(346, 402));
 
  204         imageTable.setAutoCreateRowSorter(
true);
 
  205         imageTable.setModel(
new javax.swing.table.DefaultTableModel(
 
  213         imageTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
 
  214         imageTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
 
  215         imageTable.setShowHorizontalLines(
false);
 
  216         imageTable.setShowVerticalLines(
false);
 
  217         imageTable.getTableHeader().setReorderingAllowed(
false);
 
  218         imageTable.addMouseListener(
new java.awt.event.MouseAdapter() {
 
  219             public void mouseReleased(java.awt.event.MouseEvent evt) {
 
  220                 imageTableMouseReleased(evt);
 
  223         imageTable.addKeyListener(
new java.awt.event.KeyAdapter() {
 
  224             public void keyReleased(java.awt.event.KeyEvent evt) {
 
  225                 imageTableKeyReleased(evt);
 
  228         imageScrollPane.setViewportView(imageTable);
 
  229         imageTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
 
  231         jScrollPane1.setBorder(null);
 
  233         messageTextArea.setBackground(
new java.awt.Color(240, 240, 240));
 
  234         messageTextArea.setColumns(20);
 
  235         messageTextArea.setForeground(java.awt.Color.red);
 
  236         messageTextArea.setLineWrap(
true);
 
  237         messageTextArea.setRows(3);
 
  238         messageTextArea.setBorder(null);
 
  239         messageTextArea.setDisabledTextColor(java.awt.Color.red);
 
  240         messageTextArea.setEnabled(
false);
 
  241         messageTextArea.setMargin(
new java.awt.Insets(0, 0, 0, 0));
 
  242         jScrollPane1.setViewportView(messageTextArea);
 
  244         javax.swing.GroupLayout layout = 
new javax.swing.GroupLayout(
this);
 
  245         this.setLayout(layout);
 
  246         layout.setHorizontalGroup(
 
  247             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  248             .addGroup(layout.createSequentialGroup()
 
  249                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  250                     .addGroup(layout.createSequentialGroup()
 
  252                         .addComponent(selectFolderLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 81, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  254                         .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 474, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  255                     .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, 
false)
 
  256                         .addComponent(jSeparator2, javax.swing.GroupLayout.Alignment.LEADING)
 
  257                         .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  258                             .addGroup(layout.createSequentialGroup()
 
  260                                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  261                                     .addComponent(driveListScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 160, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  262                                     .addComponent(refreshButton))
 
  263                                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  264                                 .addComponent(imageScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 377, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  265                             .addGroup(layout.createSequentialGroup()
 
  267                                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  268                                     .addGroup(layout.createSequentialGroup()
 
  269                                         .addComponent(manualRadioButton)
 
  270                                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  271                                         .addComponent(browseButton))
 
  272                                     .addComponent(importRadioButton)
 
  273                                     .addGroup(layout.createSequentialGroup()
 
  275                                         .addComponent(selectDriveLabel)
 
  276                                         .addGap(113, 113, 113)
 
  277                                         .addComponent(selectFromDriveLabel))))))
 
  278                     .addGroup(layout.createSequentialGroup()
 
  280                         .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 568, javax.swing.GroupLayout.PREFERRED_SIZE)))
 
  281                 .addContainerGap(93, Short.MAX_VALUE))
 
  283         layout.setVerticalGroup(
 
  284             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  285             .addGroup(layout.createSequentialGroup()
 
  287                 .addComponent(importRadioButton)
 
  288                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  289                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
 
  290                     .addComponent(selectDriveLabel)
 
  291                     .addComponent(selectFromDriveLabel))
 
  292                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  293                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  294                     .addComponent(imageScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
 
  295                     .addComponent(driveListScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 198, Short.MAX_VALUE))
 
  296                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  297                 .addComponent(refreshButton)
 
  299                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  300                     .addComponent(browseButton)
 
  301                     .addComponent(manualRadioButton))
 
  303                 .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  304                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  305                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  306                     .addComponent(selectFolderLabel)
 
  307                     .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  308                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  309                 .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 61, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  315         "# {0} - sparseImageDirectory",
 
  316         "LogicalImagerPanel.messageLabel.directoryDoesNotContainSparseImage=Directory {0} does not contain any images",
 
  317         "# {0} - invalidFormatDirectory",
 
  318         "LogicalImagerPanel.messageLabel.directoryFormatInvalid=Directory {0} does not match format Logical_Imager_HOSTNAME_yyyymmdd_HH_MM_SS" 
  320     private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {
 
  321         JFileChooser fileChooser = chooserHelper.getChooser();
 
  322         imageTable.clearSelection();
 
  323         manualImageDirPath = null;
 
  324         setErrorMessage(NO_IMAGE_SELECTED);
 
  325         fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
 
  326         int retval = fileChooser.showOpenDialog(
this);
 
  327         if (retval == JFileChooser.APPROVE_OPTION) {
 
  328             String path = fileChooser.getSelectedFile().getPath();
 
  329             Matcher m = regex.matcher(path);
 
  331                 File dir = Paths.get(path).toFile();
 
  332                 String[] vhdFiles = dir.list(
new FilenameFilter() {
 
  334                     public boolean accept(File dir, String name) {
 
  335                         return name.endsWith(
".vhd");
 
  338                 if (vhdFiles.length == 0) {
 
  340                     String[] directories = dir.list(
new FilenameFilter() {
 
  342                         public boolean accept(File dir, String name) {
 
  343                             return Paths.get(dir.toString(), name).toFile().isDirectory();
 
  346                     if (directories.length == 0) {
 
  348                         setErrorMessage(Bundle.LogicalImagerPanel_messageLabel_directoryDoesNotContainSparseImage(path));
 
  349                         firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), 
true, 
false);
 
  353                 manualImageDirPath = Paths.get(path);
 
  354                 setNormalMessage(path);
 
  355                 firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), 
false, 
true);
 
  357                 setErrorMessage(Bundle.LogicalImagerPanel_messageLabel_directoryFormatInvalid(path));
 
  358                 firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), 
true, 
false);
 
  361             firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), 
true, 
false);
 
  365     private void imageTableSelect() {
 
  366         int index = imageTable.getSelectedRow();
 
  368             setNormalMessage((String) imageTableModel.getValueAt(imageTable.convertRowIndexToModel(index), 2));
 
  369             firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), 
false, 
true);
 
  371             setErrorMessage(NO_IMAGE_SELECTED);
 
  372             firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), 
true, 
false);
 
  376     private boolean dirHasImagerResult(File dir) {
 
  377         String[] fList = dir.list(
new FilenameFilter() {
 
  379             public boolean accept(File dir, String name) {
 
  380                 return name.endsWith(
".vhd") || Paths.get(dir.toString(), name).toFile().isDirectory();
 
  383         return (fList != null && fList.length != 0);
 
  386     private void driveListSelect() {
 
  387         String selectedStr = driveList.getSelectedValue();
 
  388         if (selectedStr == null) {
 
  391         String driveLetter = selectedStr.substring(0, 3);
 
  392         File directory = 
new File(driveLetter);
 
  393         File[] fList = directory.listFiles();
 
  396             imageTableModel = 
new ImageTableModel();
 
  399             for (File file : fList) {
 
  400                 if (file.isDirectory() && dirHasImagerResult(file)) {
 
  401                     String dir = file.getName();
 
  402                     Matcher m = regex.matcher(dir);
 
  404                         String imageDirPath = driveLetter + dir;
 
  405                         String hostname = m.group(1);
 
  406                         String year = m.group(2);
 
  407                         String month = m.group(3);
 
  408                         String day = m.group(4);
 
  409                         String hour = m.group(5);
 
  410                         String minute = m.group(6);
 
  411                         String second = m.group(7);
 
  412                         String extractDate = year + 
"/" + month + 
"/" + day
 
  413                                 + 
" " + hour + 
":" + minute + 
":" + second;
 
  414                         imageTableModel.addRow(
new Object[]{hostname, extractDate, imageDirPath});
 
  418             selectFromDriveLabel.setText(Bundle.LogicalImagerPanel_selectAcquisitionFromDriveLabel_text()
 
  419                     + 
" " + driveLetter);
 
  420             imageTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
 
  421             imageTable.setModel(imageTableModel);
 
  422             configureImageTable();
 
  423             fixImageTableColumnWidth();
 
  425             if (imageTable.getRowCount() > 0) {
 
  426                 imageTable.setRowSelectionInterval(0, 0);
 
  429                 setErrorMessage(DRIVE_HAS_NO_IMAGES);
 
  433             setErrorMessage(DRIVE_HAS_NO_IMAGES);
 
  437     private void fixImageTableColumnWidth() {
 
  438         int width = imageScrollPane.getPreferredSize().width - 2;
 
  439         imageTable.getColumnModel().getColumn(0).setPreferredWidth((
int) (.60 * width));
 
  440         imageTable.getColumnModel().getColumn(1).setPreferredWidth((
int) (.40 * width));
 
  443     private void setErrorMessage(String msg) {
 
  444         messageTextArea.setForeground(Color.red);
 
  445         messageTextArea.setText(msg);
 
  446         pathTextField.setText(
"");
 
  449     private void setNormalMessage(String msg) {
 
  450         pathTextField.setText(msg);
 
  451         messageTextArea.setText(
"");
 
  454     private void clearImageTable() {
 
  455         imageTableModel = 
new ImageTableModel();
 
  456         imageTable.setModel(imageTableModel);
 
  457         configureImageTable();
 
  458         fixImageTableColumnWidth();
 
  461     private void toggleMouseAndKeyListeners(Component component, 
boolean isEnable) {
 
  462         component.setEnabled(isEnable);
 
  465     private void manualRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {
 
  466         browseButton.setEnabled(
true);
 
  469         toggleMouseAndKeyListeners(driveList, 
false);
 
  470         toggleMouseAndKeyListeners(driveListScrollPane, 
false);
 
  471         toggleMouseAndKeyListeners(imageScrollPane, 
false);
 
  472         toggleMouseAndKeyListeners(imageTable, 
false);
 
  474         refreshButton.setEnabled(
false);
 
  476         manualImageDirPath = null;
 
  477         setNormalMessage(
"");
 
  478         firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), 
true, 
false);
 
  481     private void importRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {
 
  482         browseButton.setEnabled(
false);
 
  484         toggleMouseAndKeyListeners(driveList, 
true);
 
  485         toggleMouseAndKeyListeners(driveListScrollPane, 
true);
 
  486         toggleMouseAndKeyListeners(imageScrollPane, 
true);
 
  487         toggleMouseAndKeyListeners(imageTable, 
true);
 
  489         refreshButton.setEnabled(
true);
 
  491         manualImageDirPath = null;
 
  492         setNormalMessage(
"");
 
  493         refreshButton.doClick();
 
  497         "LogicalImagerPanel.messageLabel.scanningExternalDrives=Scanning external drives for images ...",
 
  498         "LogicalImagerPanel.messageLabel.noExternalDriveFound=No drive found" 
  500     private void refreshButtonActionPerformed(java.awt.event.ActionEvent evt) {
 
  503         setNormalMessage(Bundle.LogicalImagerPanel_messageLabel_scanningExternalDrives());
 
  504         List<String> listData = 
new ArrayList<>();
 
  505         File[] roots = File.listRoots();
 
  506         int firstRemovableDrive = -1;
 
  508         for (File root : roots) {
 
  509             if (DriveListUtils.isNetworkDrive(root.toString().replace(
":\\", 
""))) {
 
  512             String description = FileSystemView.getFileSystemView().getSystemTypeDescription(root);
 
  513             long spaceInBytes = root.getTotalSpace();
 
  514             String sizeWithUnit = DriveListUtils.humanReadableByteCount(spaceInBytes, 
false);
 
  515             listData.add(root + 
" (" + description + 
") (" + sizeWithUnit + 
")");
 
  516             if (firstRemovableDrive == -1) {
 
  518                     FileStore fileStore = Files.getFileStore(root.toPath());
 
  519                     if ((
boolean) fileStore.getAttribute(
"volume:isRemovable")) { 
 
  520                         firstRemovableDrive = i;
 
  522                 } 
catch (IOException ignored) {
 
  524                     logger.log(Level.INFO, String.format(
"Unable to select first removable drive found: %s", ignored.getMessage()));
 
  529         driveList.setListData(listData.toArray(
new String[listData.size()]));
 
  530         if (!listData.isEmpty()) {
 
  532             driveList.setSelectedIndex(firstRemovableDrive == -1 ? 0 : firstRemovableDrive);
 
  533             driveListMouseReleased(null);
 
  534             driveList.requestFocusInWindow();
 
  536             setErrorMessage(Bundle.LogicalImagerPanel_messageLabel_noExternalDriveFound());
 
  538         firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), 
true, 
false);
 
  541     private void driveListKeyReleased(java.awt.event.KeyEvent evt) {
 
  542         if (importRadioButton.isSelected()) {
 
  544             firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), 
true, 
false);
 
  548     private void imageTableKeyReleased(java.awt.event.KeyEvent evt) {
 
  549         if (importRadioButton.isSelected()) {
 
  554     private void imageTableMouseReleased(java.awt.event.MouseEvent evt) {
 
  555         if (importRadioButton.isSelected()) {
 
  560     private void driveListMouseReleased(java.awt.event.MouseEvent evt) {
 
  561         if (importRadioButton.isSelected()) {
 
  563             firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), 
true, 
false);
 
  569     private javax.swing.JButton browseButton;
 
  570     private javax.swing.ButtonGroup buttonGroup1;
 
  571     private javax.swing.JList<String> driveList;
 
  572     private javax.swing.JScrollPane driveListScrollPane;
 
  573     private javax.swing.JScrollPane imageScrollPane;
 
  574     private javax.swing.JTable imageTable;
 
  575     private javax.swing.JRadioButton importRadioButton;
 
  576     private javax.swing.JScrollPane jScrollPane1;
 
  577     private javax.swing.JSeparator jSeparator2;
 
  578     private javax.swing.JRadioButton manualRadioButton;
 
  579     private javax.swing.JTextArea messageTextArea;
 
  580     private javax.swing.JTextField pathTextField;
 
  581     private javax.swing.JButton refreshButton;
 
  582     private javax.swing.JLabel selectDriveLabel;
 
  583     private javax.swing.JLabel selectFolderLabel;
 
  584     private javax.swing.JLabel selectFromDriveLabel;
 
  589         manualImageDirPath = null;
 
  590         setNormalMessage(
"");
 
  591         driveList.setListData(EMPTY_LIST_DATA);
 
  593         if (importRadioButton.isSelected()) {
 
  594             refreshButton.doClick();
 
  603     boolean validatePanel() {
 
  604         if (manualRadioButton.isSelected()) {
 
  605             return manualImageDirPath != null && manualImageDirPath.toFile().exists();
 
  606         } 
else if (imageTable.getSelectedRow() != -1) {
 
  607             Path path = Paths.get((String) imageTableModel.getValueAt(imageTable.convertRowIndexToModel(imageTable.getSelectedRow()), 2));
 
  608             return path != null && path.toFile().exists();
 
  614     Path getImageDirPath() {
 
  615         if (manualRadioButton.isSelected()) {
 
  616             return manualImageDirPath;
 
  617         } 
else if (imageTable.getSelectedRow() != -1) {
 
  618             return Paths.get((String) imageTableModel.getValueAt(imageTable.convertRowIndexToModel(imageTable.getSelectedRow()), 2));
 
  625     public void insertUpdate(DocumentEvent e) {
 
  629     public void removeUpdate(DocumentEvent e) {
 
  633     public void changedUpdate(DocumentEvent e) {
 
  636     void storeSettings() {
 
  644         private static final long serialVersionUID = 1L;
 
  652             "LogicalImagerPanel.imageTable.columnModel.title0=Hostname",
 
  653             "LogicalImagerPanel.imageTable.columnModel.title1=Extracted Date (GMT)",
 
  654             "LogicalImagerPanel.imageTable.columnModel.title2=Path" 
  658             String colName = null;
 
  661                     colName = Bundle.LogicalImagerPanel_imageTable_columnModel_title0();
 
  664                     colName = Bundle.LogicalImagerPanel_imageTable_columnModel_title1();
 
  667                     colName = Bundle.LogicalImagerPanel_imageTable_columnModel_title2();
 
String getColumnName(int column)
 
boolean isCellEditable(int rowIndex, int columnIndex)