Autopsy  4.20.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
LocalDiskSelectionDialog.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2018 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.casemodule;
20 
21 import java.awt.Window;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.concurrent.CancellationException;
27 import java.util.concurrent.ExecutionException;
28 import java.util.logging.Level;
29 import javax.swing.JDialog;
30 import javax.swing.SwingWorker;
31 import javax.swing.event.ListSelectionEvent;
32 import javax.swing.event.ListSelectionListener;
33 import javax.swing.event.TableModelListener;
34 import javax.swing.table.TableModel;
35 import org.openide.util.NbBundle;
41 
42 @NbBundle.Messages({
43  "LocalDiskSelectionDialog.moduleErrorMessage.title=Module Error",
44  "LocalDiskSelectionDialog.moduleErrorMessage.body=A module caused an error listening to LocalDiskPanel updates. See log to determine which module. Some data could be incomplete.",
45  "LocalDiskSelectionDialog.errorMessage.disksNotDetected=Disks were not detected. On some systems it requires admin privileges (or \"Run as administrator\").",
46  "LocalDiskSelectionDialog.errorMessage.drivesNotDetected=Local drives were not detected. Auto-detection not supported on this OS or admin privileges required",
47  "LocalDiskSelectionDialog.errorMessage.someDisksNotDetected=Some disks were not detected. On some systems it requires admin privileges (or \"Run as administrator\")."
48 })
52 @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
53 final class LocalDiskSelectionDialog extends JDialog {
54 
55  private static final Logger logger = Logger.getLogger(LocalDiskSelectionDialog.class.getName());
56  private static final long serialVersionUID = 1L;
57  private List<LocalDisk> disks;
58  private final LocalDiskModel model;
59 
63  LocalDiskSelectionDialog() {
64  super((Window) LocalDiskPanel.getDefault().getTopLevelAncestor(), ModalityType.MODELESS);
65 
66  this.model = new LocalDiskModel();
67  this.disks = new ArrayList<>();
68 
69  initComponents();
70  refreshTable();
71 
72  localDiskTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
73  @Override
74  public void valueChanged(ListSelectionEvent e) {
75  int selectedRow = localDiskTable.getSelectedRow();
76  okButton.setEnabled(selectedRow >= 0 && selectedRow < disks.size());
77  }
78  });
79  }
80 
84  void display() {
85  setModal(true);
86  setSize(getPreferredSize());
87  setLocationRelativeTo(this.getParent());
88  setAlwaysOnTop(false);
89  setVisible(true);
90  }
91 
97  @SuppressWarnings("unchecked")
98  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
99  private void initComponents() {
100 
101  selectLocalDiskLabel = new javax.swing.JLabel();
102  errorLabel = new javax.swing.JLabel();
103  localDiskScrollPane = new javax.swing.JScrollPane();
104  localDiskTable = new javax.swing.JTable();
105  refreshLocalDisksButton = new javax.swing.JButton();
106  okButton = new javax.swing.JButton();
107  cancelButton = new javax.swing.JButton();
108 
109  setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
110  setTitle(org.openide.util.NbBundle.getMessage(LocalDiskSelectionDialog.class, "LocalDiskSelectionDialog.title")); // NOI18N
111  setAlwaysOnTop(true);
112  setResizable(false);
113 
114  org.openide.awt.Mnemonics.setLocalizedText(selectLocalDiskLabel, org.openide.util.NbBundle.getMessage(LocalDiskSelectionDialog.class, "LocalDiskSelectionDialog.selectLocalDiskLabel.text")); // NOI18N
115 
116  errorLabel.setForeground(new java.awt.Color(255, 0, 0));
117  org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(LocalDiskSelectionDialog.class, "LocalDiskSelectionDialog.errorLabel.text")); // NOI18N
118 
119  localDiskTable.setModel(model);
120  localDiskTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
121  localDiskScrollPane.setViewportView(localDiskTable);
122 
123  org.openide.awt.Mnemonics.setLocalizedText(refreshLocalDisksButton, org.openide.util.NbBundle.getMessage(LocalDiskSelectionDialog.class, "LocalDiskSelectionDialog.refreshLocalDisksButton.text")); // NOI18N
124  refreshLocalDisksButton.addActionListener(new java.awt.event.ActionListener() {
125  public void actionPerformed(java.awt.event.ActionEvent evt) {
126  refreshLocalDisksButtonActionPerformed(evt);
127  }
128  });
129 
130  org.openide.awt.Mnemonics.setLocalizedText(okButton, org.openide.util.NbBundle.getMessage(LocalDiskSelectionDialog.class, "LocalDiskSelectionDialog.okButton.text")); // NOI18N
131  okButton.setEnabled(false);
132  okButton.addActionListener(new java.awt.event.ActionListener() {
133  public void actionPerformed(java.awt.event.ActionEvent evt) {
134  okButtonActionPerformed(evt);
135  }
136  });
137 
138  org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(LocalDiskSelectionDialog.class, "LocalDiskSelectionDialog.cancelButton.text")); // NOI18N
139  cancelButton.addActionListener(new java.awt.event.ActionListener() {
140  public void actionPerformed(java.awt.event.ActionEvent evt) {
141  cancelButtonActionPerformed(evt);
142  }
143  });
144 
145  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
146  getContentPane().setLayout(layout);
147  layout.setHorizontalGroup(
148  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
149  .addGroup(layout.createSequentialGroup()
150  .addContainerGap()
151  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
152  .addComponent(localDiskScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 560, Short.MAX_VALUE)
153  .addGroup(layout.createSequentialGroup()
154  .addComponent(okButton, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
155  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
156  .addComponent(cancelButton, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
157  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
158  .addComponent(refreshLocalDisksButton))
159  .addGroup(layout.createSequentialGroup()
160  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
161  .addComponent(selectLocalDiskLabel)
162  .addComponent(errorLabel))
163  .addGap(0, 0, Short.MAX_VALUE)))
164  .addContainerGap())
165  );
166  layout.setVerticalGroup(
167  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
168  .addGroup(layout.createSequentialGroup()
169  .addGap(6, 6, 6)
170  .addComponent(selectLocalDiskLabel)
171  .addGap(4, 4, 4)
172  .addComponent(localDiskScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
173  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
174  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
175  .addComponent(refreshLocalDisksButton)
176  .addComponent(okButton)
177  .addComponent(cancelButton))
178  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
179  .addComponent(errorLabel)
180  .addContainerGap(27, Short.MAX_VALUE))
181  );
182 
183  pack();
184  }// </editor-fold>//GEN-END:initComponents
185 
186  private void refreshLocalDisksButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshLocalDisksButtonActionPerformed
187  refreshTable();
188  }//GEN-LAST:event_refreshLocalDisksButtonActionPerformed
189 
190  private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
191  dispose();
192  }//GEN-LAST:event_okButtonActionPerformed
193 
194  private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
195  localDiskTable.clearSelection();
196  dispose();
197  }//GEN-LAST:event_cancelButtonActionPerformed
198 
199  // Variables declaration - do not modify//GEN-BEGIN:variables
200  private javax.swing.JButton cancelButton;
201  private javax.swing.JLabel errorLabel;
202  private javax.swing.JScrollPane localDiskScrollPane;
203  private javax.swing.JTable localDiskTable;
204  private javax.swing.JButton okButton;
205  private javax.swing.JButton refreshLocalDisksButton;
206  private javax.swing.JLabel selectLocalDiskLabel;
207  // End of variables declaration//GEN-END:variables
208 
212  private void fireUpdateEvent() {
213  try {
214  firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
215  } catch (Exception e) {
216  logger.log(Level.SEVERE, "LocalDiskSelectionDialog listener threw exception", e); //NON-NLS
217  MessageNotifyUtil.Notify.show(Bundle.LocalDiskSelectionDialog_moduleErrorMessage_title(),
218  Bundle.LocalDiskSelectionDialog_moduleErrorMessage_body(),
219  MessageNotifyUtil.MessageType.ERROR);
220  }
221  }
222 
228  String getContentPaths() {
229  LocalDisk selected = getLocalDiskSelection();
230  if (selected != null) {
231  return selected.getPath();
232  }
233  return "";
234  }
235 
239  private void refreshTable() {
240  model.loadDisks();
241  localDiskTable.clearSelection();
242  }
243 
249  LocalDisk getLocalDiskSelection() {
250  if (disks.size() > 0) {
251  int selectedRow = localDiskTable.getSelectedRow();
252  if (selectedRow >= 0 && selectedRow < disks.size()) {
253  return disks.get(selectedRow);
254  }
255  }
256  return null;
257  }
258 
259  @NbBundle.Messages({
260  "LocalDiskSelectionDialog.tableMessage.loading=Loading local disks...",
261  "LocalDiskSelectionDialog.tableMessage.noDrives=No Accessible Drives",
262  })
266  private class LocalDiskModel implements TableModel {
267 
268  private LocalDiskThread worker = null;
269  private boolean ready = false;
270  private volatile boolean loadingDisks = false;
271 
272  private void loadDisks() {
273 
274  // if there is a worker already building the lists, then cancel it first.
275  if (loadingDisks && worker != null) {
276  worker.cancel(false);
277  }
278 
279  // Clear the lists
280  errorLabel.setText("");
281  localDiskTable.setEnabled(false);
282  ready = false;
283  loadingDisks = true;
284  worker = new LocalDiskThread();
285  worker.execute();
286  }
287 
288  @Override
289  public int getRowCount() {
290  if (disks.isEmpty()) {
291  return 0;
292  }
293  return disks.size();
294  }
295 
296  @Override
297  public int getColumnCount() {
298  return 2;
299 
300  }
301 
302  @NbBundle.Messages({
303  "LocalDiskSelectionDialog.columnName.diskName=Disk Name",
304  "LocalDiskSelectionDialog.columnName.diskSize=Disk Size"
305  })
306 
307  @Override
308  public String getColumnName(int columnIndex) {
309  switch (columnIndex) {
310  case 0:
311  return Bundle.LocalDiskSelectionDialog_columnName_diskName();
312  case 1:
313  return Bundle.LocalDiskSelectionDialog_columnName_diskSize();
314  default:
315  return "Unnamed"; //NON-NLS
316  }
317  }
318 
319  @Override
320  public Class<?> getColumnClass(int columnIndex) {
321  return String.class;
322  }
323 
324  @Override
325  public boolean isCellEditable(int rowIndex, int columnIndex) {
326  return false;
327  }
328 
329  @Override
330  public Object getValueAt(int rowIndex, int columnIndex) {
331  if (ready) {
332  if (disks.isEmpty()) {
333  return Bundle.LocalDiskSelectionDialog_tableMessage_noDrives();
334  }
335  switch (columnIndex) {
336  case 0:
337  return disks.get(rowIndex).getName();
338  case 1:
339  return disks.get(rowIndex).getReadableSize();
340  default:
341  return disks.get(rowIndex).getPath();
342  }
343  } else {
344  return Bundle.LocalDiskSelectionDialog_tableMessage_loading();
345  }
346  }
347 
348  @Override
349  public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
350  //setter does nothing they should not be able to modify table
351  }
352 
353  @Override
354  public void addTableModelListener(TableModelListener l) {
355 
356  }
357 
358  @Override
359  public void removeTableModelListener(TableModelListener l) {
360 
361  }
362 
367  class LocalDiskThread extends SwingWorker<Object, Void> {
368 
369  private final Logger logger = Logger.getLogger(LocalDiskThread.class.getName());
370  private List<LocalDisk> physicalDrives = new ArrayList<>();
371  private List<LocalDisk> partitions = new ArrayList<>();
372 
373  @Override
374  protected Object doInBackground() throws Exception {
375  // Populate the lists
376  physicalDrives = new ArrayList<>();
377  partitions = new ArrayList<>();
378  physicalDrives = PlatformUtil.getPhysicalDrives();
379  partitions = PlatformUtil.getPartitions();
380  return null;
381  }
382 
387  private void displayErrors() {
388  if (physicalDrives.isEmpty() && partitions.isEmpty()) {
389  if (PlatformUtil.isWindowsOS()) {
390  errorLabel.setText(Bundle.LocalDiskSelectionDialog_errorMessage_disksNotDetected());
391  errorLabel.setToolTipText(Bundle.LocalDiskSelectionDialog_errorMessage_disksNotDetected());
392  } else {
393  errorLabel.setText(Bundle.LocalDiskSelectionDialog_errorMessage_drivesNotDetected());
394  errorLabel.setToolTipText(Bundle.LocalDiskSelectionDialog_errorMessage_drivesNotDetected());
395  }
396  errorLabel.setVisible(true);
397  localDiskTable.setEnabled(false);
398  } else if (physicalDrives.isEmpty()) {
399  errorLabel.setText(Bundle.LocalDiskSelectionDialog_errorMessage_someDisksNotDetected());
400  errorLabel.setToolTipText(Bundle.LocalDiskSelectionDialog_errorMessage_someDisksNotDetected());
401  errorLabel.setVisible(true);
402  }
403  }
404 
405  @Override
406  protected void done() {
407  try {
408  super.get(); //block and get all exceptions thrown while doInBackground()
409  } catch (CancellationException ex) {
410  logger.log(Level.INFO, "Loading local disks was canceled."); //NON-NLS
411  } catch (InterruptedException ex) {
412  logger.log(Level.INFO, "Loading local disks was interrupted."); //NON-NLS
413  } catch (ExecutionException ex) {
414  logger.log(Level.SEVERE, "Fatal error when loading local disks", ex); //NON-NLS
415  } finally {
416  if (!this.isCancelled()) {
417  displayErrors();
418  worker = null;
419  loadingDisks = false;
420  disks = new ArrayList<>();
421  disks.addAll(physicalDrives);
422  disks.addAll(partitions);
423  if (disks.size() > 0) {
424  localDiskTable.setEnabled(true);
425  localDiskTable.clearSelection();
426 
427  // Remove the partition the application is running on.
428  String userConfigPath = PlatformUtil.getUserConfigDirectory();
429  for (Iterator<LocalDisk> iterator = disks.iterator(); iterator.hasNext();) {
430  LocalDisk disk = iterator.next();
431  String diskPath = disk.getPath();
432  if (diskPath.startsWith("\\\\.\\")) {
433  // Strip out UNC prefix to get the drive letter.
434  diskPath = diskPath.substring(4);
435  }
436  if (userConfigPath.startsWith(diskPath)) {
437  iterator.remove();
438  }
439  }
440 
441  Collections.sort(disks, (LocalDisk disk1, LocalDisk disk2) -> disk1.getName().compareToIgnoreCase(disk2.getName()));
442  }
443  fireUpdateEvent();
444  ready = true;
445  }
446  }
447  localDiskTable.revalidate();
448  }
449  }
450  }
451 }
static List< LocalDisk > getPhysicalDrives()
synchronized static Logger getLogger(String name)
Definition: Logger.java:124

Copyright © 2012-2022 Basis Technology. Generated on: Tue Aug 1 2023
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.