Autopsy  4.19.3
Graphical digital forensics platform for The Sleuth Kit and other tools.
LogicalImagerPanel.java
Go to the documentation of this file.
1 /*
2  * Autopsy
3  *
4  * Copyright 2019-2021 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.logicalimager.dsp;
20 
21 import java.awt.Color;
22 import java.awt.Component;
23 import java.io.File;
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;
48 
53 @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") // UI widgets cause lots of false positives
58 final class LogicalImagerPanel extends JPanel implements DocumentListener {
59 
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 = {};
67 
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;
72 
79  private LogicalImagerPanel(String context) {
80  initComponents();
81  configureImageTable();
82  jScrollPane1.setBorder(null);
83  clearImageTable();
84  chooserHelper = new JFileChooserFactory();
85  }
86 
91  private void configureImageTable() {
92  //hide path column while leaving it in model
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);
97  }
98  //sort on specified column in decending order, the first call will toggle to ascending order, the second to descending order
99  imageTable.getRowSorter().toggleSortOrder(COLUMN_TO_SORT_ON_INDEX);
100  imageTable.getRowSorter().toggleSortOrder(COLUMN_TO_SORT_ON_INDEX);
101  }
102  }
103 
112  static synchronized LogicalImagerPanel createInstance(String context) {
113  LogicalImagerPanel instance = new LogicalImagerPanel(context);
114  // post-constructor initialization of listener support without leaking references of uninitialized objects
115  instance.imageTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
116  return instance;
117  }
118 
124  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
125  private void initComponents() {
126 
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();
143 
144  setMinimumSize(new java.awt.Dimension(0, 65));
145  setPreferredSize(new java.awt.Dimension(403, 65));
146 
147  org.openide.awt.Mnemonics.setLocalizedText(browseButton, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.browseButton.text")); // NOI18N
148  browseButton.setEnabled(false);
149  browseButton.addActionListener(new java.awt.event.ActionListener() {
150  public void actionPerformed(java.awt.event.ActionEvent evt) {
151  browseButtonActionPerformed(evt);
152  }
153  });
154 
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")); // NOI18N
158  importRadioButton.setToolTipText("");
159  importRadioButton.addActionListener(new java.awt.event.ActionListener() {
160  public void actionPerformed(java.awt.event.ActionEvent evt) {
161  importRadioButtonActionPerformed(evt);
162  }
163  });
164 
165  buttonGroup1.add(manualRadioButton);
166  org.openide.awt.Mnemonics.setLocalizedText(manualRadioButton, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.manualRadioButton.text")); // NOI18N
167  manualRadioButton.addActionListener(new java.awt.event.ActionListener() {
168  public void actionPerformed(java.awt.event.ActionEvent evt) {
169  manualRadioButtonActionPerformed(evt);
170  }
171  });
172 
173  pathTextField.setDisabledTextColor(java.awt.Color.black);
174  pathTextField.setEnabled(false);
175 
176  org.openide.awt.Mnemonics.setLocalizedText(selectFolderLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.selectFolderLabel.text")); // NOI18N
177 
178  org.openide.awt.Mnemonics.setLocalizedText(selectDriveLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.selectDriveLabel.text")); // NOI18N
179 
180  org.openide.awt.Mnemonics.setLocalizedText(selectFromDriveLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.selectFromDriveLabel.text")); // NOI18N
181 
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);
186  }
187  });
188  driveList.addKeyListener(new java.awt.event.KeyAdapter() {
189  public void keyReleased(java.awt.event.KeyEvent evt) {
190  driveListKeyReleased(evt);
191  }
192  });
193  driveListScrollPane.setViewportView(driveList);
194 
195  org.openide.awt.Mnemonics.setLocalizedText(refreshButton, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.refreshButton.text")); // NOI18N
196  refreshButton.addActionListener(new java.awt.event.ActionListener() {
197  public void actionPerformed(java.awt.event.ActionEvent evt) {
198  refreshButtonActionPerformed(evt);
199  }
200  });
201 
202  imageScrollPane.setPreferredSize(new java.awt.Dimension(346, 402));
203 
204  imageTable.setAutoCreateRowSorter(true);
205  imageTable.setModel(new javax.swing.table.DefaultTableModel(
206  new Object [][] {
207 
208  },
209  new String [] {
210 
211  }
212  ));
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);
221  }
222  });
223  imageTable.addKeyListener(new java.awt.event.KeyAdapter() {
224  public void keyReleased(java.awt.event.KeyEvent evt) {
225  imageTableKeyReleased(evt);
226  }
227  });
228  imageScrollPane.setViewportView(imageTable);
229  imageTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
230 
231  jScrollPane1.setBorder(null);
232 
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);
243 
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()
251  .addGap(10, 10, 10)
252  .addComponent(selectFolderLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 81, javax.swing.GroupLayout.PREFERRED_SIZE)
253  .addGap(13, 13, 13)
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()
259  .addGap(41, 41, 41)
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()
266  .addGap(20, 20, 20)
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()
274  .addGap(21, 21, 21)
275  .addComponent(selectDriveLabel)
276  .addGap(113, 113, 113)
277  .addComponent(selectFromDriveLabel))))))
278  .addGroup(layout.createSequentialGroup()
279  .addContainerGap()
280  .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 568, javax.swing.GroupLayout.PREFERRED_SIZE)))
281  .addContainerGap(93, Short.MAX_VALUE))
282  );
283  layout.setVerticalGroup(
284  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
285  .addGroup(layout.createSequentialGroup()
286  .addGap(16, 16, 16)
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)
298  .addGap(18, 18, 18)
299  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
300  .addComponent(browseButton)
301  .addComponent(manualRadioButton))
302  .addGap(18, 18, 18)
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)
310  .addGap(6, 6, 6))
311  );
312  }// </editor-fold>//GEN-END:initComponents
313 
314  @Messages({
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"
319  })
320  private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed
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);
330  if (m.find()) {
331  File dir = Paths.get(path).toFile();
332  String[] vhdFiles = dir.list(new FilenameFilter() {
333  @Override
334  public boolean accept(File dir, String name) {
335  return name.endsWith(".vhd");
336  }
337  });
338  if (vhdFiles.length == 0) {
339  // No VHD files, try directories for individual files
340  String[] directories = dir.list(new FilenameFilter() {
341  @Override
342  public boolean accept(File dir, String name) {
343  return Paths.get(dir.toString(), name).toFile().isDirectory();
344  }
345  });
346  if (directories.length == 0) {
347  // No directories, bail
348  setErrorMessage(Bundle.LogicalImagerPanel_messageLabel_directoryDoesNotContainSparseImage(path));
349  firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), true, false);
350  return;
351  }
352  }
353  manualImageDirPath = Paths.get(path);
354  setNormalMessage(path);
355  firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
356  } else {
357  setErrorMessage(Bundle.LogicalImagerPanel_messageLabel_directoryFormatInvalid(path));
358  firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), true, false);
359  }
360  } else {
361  firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), true, false);
362  }
363  }//GEN-LAST:event_browseButtonActionPerformed
364 
365  private void imageTableSelect() {
366  int index = imageTable.getSelectedRow();
367  if (index != -1) {
368  setNormalMessage((String) imageTableModel.getValueAt(imageTable.convertRowIndexToModel(index), 2));
369  firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
370  } else {
371  setErrorMessage(NO_IMAGE_SELECTED);
372  firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), true, false);
373  }
374  }
375 
376  private boolean dirHasImagerResult(File dir) {
377  String[] fList = dir.list(new FilenameFilter() {
378  @Override
379  public boolean accept(File dir, String name) {
380  return name.endsWith(".vhd") || Paths.get(dir.toString(), name).toFile().isDirectory();
381  }
382  });
383  return (fList != null && fList.length != 0);
384  }
385 
386  private void driveListSelect() {
387  String selectedStr = driveList.getSelectedValue();
388  if (selectedStr == null) {
389  return;
390  }
391  String driveLetter = selectedStr.substring(0, 3);
392  File directory = new File(driveLetter);
393  File[] fList = directory.listFiles();
394 
395  if (fList != null) {
396  imageTableModel = new ImageTableModel();
397  // Find all directories with name like Logical_Imager_HOSTNAME_yyyymmdd_HH_MM_SS
398  // and has Logical Imager result in it
399  for (File file : fList) {
400  if (file.isDirectory() && dirHasImagerResult(file)) {
401  String dir = file.getName();
402  Matcher m = regex.matcher(dir);
403  if (m.find()) {
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});
415  }
416  }
417  }
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();
424  // If there are any images, select the first one
425  if (imageTable.getRowCount() > 0) {
426  imageTable.setRowSelectionInterval(0, 0);
427  imageTableSelect();
428  } else {
429  setErrorMessage(DRIVE_HAS_NO_IMAGES);
430  }
431  } else {
432  clearImageTable();
433  setErrorMessage(DRIVE_HAS_NO_IMAGES);
434  }
435  }
436 
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));
441  }
442 
443  private void setErrorMessage(String msg) {
444  messageTextArea.setForeground(Color.red);
445  messageTextArea.setText(msg);
446  pathTextField.setText("");
447  }
448 
449  private void setNormalMessage(String msg) {
450  pathTextField.setText(msg);
451  messageTextArea.setText("");
452  }
453 
454  private void clearImageTable() {
455  imageTableModel = new ImageTableModel();
456  imageTable.setModel(imageTableModel);
457  configureImageTable();
458  fixImageTableColumnWidth();
459  }
460 
461  private void toggleMouseAndKeyListeners(Component component, boolean isEnable) {
462  component.setEnabled(isEnable);
463  }
464 
465  private void manualRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_manualRadioButtonActionPerformed
466  browseButton.setEnabled(true);
467 
468  // disable import panel
469  toggleMouseAndKeyListeners(driveList, false);
470  toggleMouseAndKeyListeners(driveListScrollPane, false);
471  toggleMouseAndKeyListeners(imageScrollPane, false);
472  toggleMouseAndKeyListeners(imageTable, false);
473 
474  refreshButton.setEnabled(false);
475 
476  manualImageDirPath = null;
477  setNormalMessage("");
478  firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), true, false);
479  }//GEN-LAST:event_manualRadioButtonActionPerformed
480 
481  private void importRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importRadioButtonActionPerformed
482  browseButton.setEnabled(false);
483 
484  toggleMouseAndKeyListeners(driveList, true);
485  toggleMouseAndKeyListeners(driveListScrollPane, true);
486  toggleMouseAndKeyListeners(imageScrollPane, true);
487  toggleMouseAndKeyListeners(imageTable, true);
488 
489  refreshButton.setEnabled(true);
490 
491  manualImageDirPath = null;
492  setNormalMessage("");
493  refreshButton.doClick();
494  }//GEN-LAST:event_importRadioButtonActionPerformed
495 
496  @Messages({
497  "LogicalImagerPanel.messageLabel.scanningExternalDrives=Scanning external drives for images ...",
498  "LogicalImagerPanel.messageLabel.noExternalDriveFound=No drive found"
499  })
500  private void refreshButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshButtonActionPerformed
501  // Scan external drives for vhd images
502  clearImageTable();
503  setNormalMessage(Bundle.LogicalImagerPanel_messageLabel_scanningExternalDrives());
504  List<String> listData = new ArrayList<>();
505  File[] roots = File.listRoots();
506  int firstRemovableDrive = -1;
507  int i = 0;
508  for (File root : roots) {
509  if (DriveListUtils.isNetworkDrive(root.toString().replace(":\\", ""))) {
510  continue;
511  }
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) {
517  try {
518  FileStore fileStore = Files.getFileStore(root.toPath());
519  if ((boolean) fileStore.getAttribute("volume:isRemovable")) { //NON-NLS
520  firstRemovableDrive = i;
521  }
522  } catch (IOException ignored) {
523  //unable to get this removable drive for default selection will try and select next removable drive by default
524  logger.log(Level.INFO, String.format("Unable to select first removable drive found: %s", ignored.getMessage()));
525  }
526  }
527  i++;
528  }
529  driveList.setListData(listData.toArray(new String[listData.size()]));
530  if (!listData.isEmpty()) {
531  // auto-select the first external drive, if any
532  driveList.setSelectedIndex(firstRemovableDrive == -1 ? 0 : firstRemovableDrive);
533  driveListMouseReleased(null);
534  driveList.requestFocusInWindow();
535  } else {
536  setErrorMessage(Bundle.LogicalImagerPanel_messageLabel_noExternalDriveFound());
537  }
538  firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), true, false);
539  }//GEN-LAST:event_refreshButtonActionPerformed
540 
541  private void driveListKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_driveListKeyReleased
542  if (importRadioButton.isSelected()) {
543  driveListSelect();
544  firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), true, false);
545  }
546  }//GEN-LAST:event_driveListKeyReleased
547 
548  private void imageTableKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_imageTableKeyReleased
549  if (importRadioButton.isSelected()) {
550  imageTableSelect();
551  }
552  }//GEN-LAST:event_imageTableKeyReleased
553 
554  private void imageTableMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_imageTableMouseReleased
555  if (importRadioButton.isSelected()) {
556  imageTableSelect();
557  }
558  }//GEN-LAST:event_imageTableMouseReleased
559 
560  private void driveListMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_driveListMouseReleased
561  if (importRadioButton.isSelected()) {
562  driveListSelect();
563  firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), true, false);
564  }
565  }//GEN-LAST:event_driveListMouseReleased
566 
567 
568  // Variables declaration - do not modify//GEN-BEGIN:variables
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;
585  // End of variables declaration//GEN-END:variables
586 
587  void reset() {
588  //reset the UI elements to default
589  manualImageDirPath = null;
590  setNormalMessage("");
591  driveList.setListData(EMPTY_LIST_DATA);
592  clearImageTable();
593  if (importRadioButton.isSelected()) {
594  refreshButton.doClick();
595  }
596  }
597 
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();
609  } else {
610  return false;
611  }
612  }
613 
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));
619  } else {
620  return null;
621  }
622  }
623 
624  @Override
625  public void insertUpdate(DocumentEvent e) {
626  }
627 
628  @Override
629  public void removeUpdate(DocumentEvent e) {
630  }
631 
632  @Override
633  public void changedUpdate(DocumentEvent e) {
634  }
635 
636  void storeSettings() {
637  }
638 
642  private class ImageTableModel extends DefaultTableModel {
643 
644  private static final long serialVersionUID = 1L;
645 
646  @Override
647  public int getColumnCount() {
648  return 3;
649  }
650 
651  @Messages({
652  "LogicalImagerPanel.imageTable.columnModel.title0=Hostname",
653  "LogicalImagerPanel.imageTable.columnModel.title1=Extracted Date (GMT)",
654  "LogicalImagerPanel.imageTable.columnModel.title2=Path"
655  })
656  @Override
657  public String getColumnName(int column) {
658  String colName = null;
659  switch (column) {
660  case 0:
661  colName = Bundle.LogicalImagerPanel_imageTable_columnModel_title0();
662  break;
663  case 1:
664  colName = Bundle.LogicalImagerPanel_imageTable_columnModel_title1();
665  break;
666  case 2:
667  colName = Bundle.LogicalImagerPanel_imageTable_columnModel_title2();
668  break;
669  default:
670  break;
671  }
672  return colName;
673  }
674 
675  @Override
676  public boolean isCellEditable(int rowIndex, int columnIndex) {
677  return false;
678  }
679  }
680 }

Copyright © 2012-2022 Basis Technology. Generated on: Thu Oct 6 2022
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.