19 package org.sleuthkit.autopsy.casemodule;
 
   22 import java.nio.file.Paths;
 
   23 import java.util.ArrayList;
 
   24 import java.util.Calendar;
 
   25 import java.util.List;
 
   26 import java.util.SimpleTimeZone;
 
   27 import java.util.TimeZone;
 
   28 import java.util.concurrent.CancellationException;
 
   29 import java.util.logging.Level;
 
   30 import javax.swing.JFileChooser;
 
   31 import javax.swing.JPanel;
 
   32 import javax.swing.SwingWorker;
 
   33 import javax.swing.event.ListSelectionEvent;
 
   34 import javax.swing.event.ListSelectionListener;
 
   35 import javax.swing.event.TableModelListener;
 
   36 import javax.swing.table.TableModel;
 
   37 import org.openide.util.NbBundle;
 
   45 @NbBundle.Messages({
"LocalDiskPanel.refreshTablebutton.text=Refresh Local Disks" 
   51 final class LocalDiskPanel extends JPanel {
 
   53     private static final Logger logger = Logger.getLogger(LocalDiskPanel.class.getName());
 
   54     private static LocalDiskPanel instance;
 
   55     private static final long serialVersionUID = 1L;
 
   56     private List<LocalDisk> disks;
 
   57     private boolean enableNext = 
false;
 
   58     private final LocalDiskModel model;
 
   59     private final JFileChooser fc = 
new JFileChooser();
 
   65         this.model = 
new LocalDiskModel();
 
   67         this.disks = 
new ArrayList<>();
 
   72         diskTable.getSelectionModel().addListSelectionListener(
new ListSelectionListener() {
 
   74             public void valueChanged(ListSelectionEvent e) {
 
   75                 if (diskTable.getSelectedRow() >= 0 && diskTable.getSelectedRow() < disks.size()) {
 
   77                     setPotentialImageWriterPath(disks.get(diskTable.getSelectedRow()));
 
   79                         firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), 
false, 
true);
 
   80                     } 
catch (Exception ex) {
 
   81                         logger.log(Level.SEVERE, 
"LocalDiskPanel listener threw exception", e); 
 
   82                         MessageNotifyUtil.Notify.show(NbBundle.getMessage(
this.getClass(), 
"LocalDiskPanel.moduleErr"),
 
   83                                 NbBundle.getMessage(
this.getClass(), 
"LocalDiskPanel.moduleErr.msg"),
 
   84                                 MessageNotifyUtil.MessageType.ERROR);
 
   89                         firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), 
false, 
true);
 
   90                     } 
catch (Exception ex) {
 
   91                         logger.log(Level.SEVERE, 
"LocalDiskPanel listener threw exception", e); 
 
   92                         MessageNotifyUtil.Notify.show(NbBundle.getMessage(
this.getClass(), 
"LocalDiskPanel.moduleErr"),
 
   93                                 NbBundle.getMessage(
this.getClass(), 
"LocalDiskPanel.moduleErr.msg"),
 
   94                                 MessageNotifyUtil.MessageType.ERROR);
 
  104     static synchronized LocalDiskPanel getDefault() {
 
  105         if (instance == null) {
 
  106             instance = 
new LocalDiskPanel();
 
  111     @SuppressWarnings(
"unchecked")
 
  112     private 
void customInit() {
 
  113         errorLabel.setVisible(
false);
 
  114         errorLabel.setText(
"");
 
  115         diskTable.setEnabled(
false);
 
  116         imageWriterErrorLabel.setVisible(
false);
 
  117         imageWriterErrorLabel.setText(
"");
 
  118         if(! PlatformUtil.isWindowsOS()){
 
  119             copyImageCheckbox.setSelected(
false);
 
  120             copyImageCheckbox.setEnabled(
false);
 
  122         pathTextField.setEnabled(copyImageCheckbox.isSelected());
 
  123         browseButton.setEnabled(copyImageCheckbox.isSelected());
 
  124         changeDatabasePathCheckbox.setEnabled(copyImageCheckbox.isSelected());
 
  132     @SuppressWarnings(
"unchecked")
 
  134     private 
void initComponents() {
 
  136         diskLabel = 
new javax.swing.JLabel();
 
  137         errorLabel = 
new javax.swing.JLabel();
 
  138         timeZoneLabel = 
new javax.swing.JLabel();
 
  139         timeZoneComboBox = 
new javax.swing.JComboBox<>();
 
  140         noFatOrphansCheckbox = 
new javax.swing.JCheckBox();
 
  141         descLabel = 
new javax.swing.JLabel();
 
  142         jScrollPane1 = 
new javax.swing.JScrollPane();
 
  143         diskTable = 
new javax.swing.JTable();
 
  144         copyImageCheckbox = 
new javax.swing.JCheckBox();
 
  145         pathTextField = 
new javax.swing.JTextField();
 
  146         browseButton = 
new javax.swing.JButton();
 
  147         jLabel1 = 
new javax.swing.JLabel();
 
  148         imageWriterErrorLabel = 
new javax.swing.JLabel();
 
  149         changeDatabasePathCheckbox = 
new javax.swing.JCheckBox();
 
  150         refreshTablebutton = 
new javax.swing.JButton();
 
  152         setMinimumSize(
new java.awt.Dimension(0, 420));
 
  153         setPreferredSize(
new java.awt.Dimension(485, 410));
 
  155         diskLabel.setFont(diskLabel.getFont().deriveFont(diskLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  156         org.openide.awt.Mnemonics.setLocalizedText(diskLabel, 
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, 
"LocalDiskPanel.diskLabel.text")); 
 
  158         errorLabel.setFont(errorLabel.getFont().deriveFont(errorLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  159         errorLabel.setForeground(
new java.awt.Color(255, 0, 0));
 
  160         org.openide.awt.Mnemonics.setLocalizedText(errorLabel, 
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, 
"LocalDiskPanel.errorLabel.text")); 
 
  162         timeZoneLabel.setFont(timeZoneLabel.getFont().deriveFont(timeZoneLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  163         org.openide.awt.Mnemonics.setLocalizedText(timeZoneLabel, 
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, 
"LocalDiskPanel.timeZoneLabel.text")); 
 
  165         timeZoneComboBox.setFont(timeZoneComboBox.getFont().deriveFont(timeZoneComboBox.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  166         timeZoneComboBox.setMaximumRowCount(30);
 
  168         noFatOrphansCheckbox.setFont(noFatOrphansCheckbox.getFont().deriveFont(noFatOrphansCheckbox.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  169         org.openide.awt.Mnemonics.setLocalizedText(noFatOrphansCheckbox, 
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, 
"LocalDiskPanel.noFatOrphansCheckbox.text")); 
 
  170         noFatOrphansCheckbox.setToolTipText(
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, 
"LocalDiskPanel.noFatOrphansCheckbox.toolTipText")); 
 
  172         descLabel.setFont(descLabel.getFont().deriveFont(descLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  173         org.openide.awt.Mnemonics.setLocalizedText(descLabel, 
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, 
"LocalDiskPanel.descLabel.text")); 
 
  175         diskTable.setModel(model);
 
  176         diskTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
 
  177         jScrollPane1.setViewportView(diskTable);
 
  179         org.openide.awt.Mnemonics.setLocalizedText(copyImageCheckbox, 
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, 
"LocalDiskPanel.copyImageCheckbox.text")); 
 
  180         copyImageCheckbox.addActionListener(
new java.awt.event.ActionListener() {
 
  181             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  182                 copyImageCheckboxActionPerformed(evt);
 
  186         pathTextField.setText(
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, 
"LocalDiskPanel.pathTextField.text")); 
 
  187         pathTextField.addKeyListener(
new java.awt.event.KeyAdapter() {
 
  188             public void keyReleased(java.awt.event.KeyEvent evt) {
 
  189                 pathTextFieldKeyReleased(evt);
 
  193         org.openide.awt.Mnemonics.setLocalizedText(browseButton, 
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, 
"LocalDiskPanel.browseButton.text")); 
 
  194         browseButton.addActionListener(
new java.awt.event.ActionListener() {
 
  195             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  196                 browseButtonActionPerformed(evt);
 
  200         org.openide.awt.Mnemonics.setLocalizedText(jLabel1, 
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, 
"LocalDiskPanel.jLabel1.text")); 
 
  202         imageWriterErrorLabel.setFont(imageWriterErrorLabel.getFont().deriveFont(imageWriterErrorLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  203         imageWriterErrorLabel.setForeground(
new java.awt.Color(255, 0, 0));
 
  204         org.openide.awt.Mnemonics.setLocalizedText(imageWriterErrorLabel, 
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, 
"LocalDiskPanel.imageWriterErrorLabel.text")); 
 
  206         org.openide.awt.Mnemonics.setLocalizedText(changeDatabasePathCheckbox, 
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, 
"LocalDiskPanel.changeDatabasePathCheckbox.text")); 
 
  208         org.openide.awt.Mnemonics.setLocalizedText(refreshTablebutton, 
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, 
"LocalDiskPanel.refreshTablebutton.text")); 
 
  209         refreshTablebutton.addActionListener(
new java.awt.event.ActionListener() {
 
  210             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  211                 refreshTablebuttonActionPerformed(evt);
 
  215         javax.swing.GroupLayout layout = 
new javax.swing.GroupLayout(
this);
 
  216         this.setLayout(layout);
 
  217         layout.setHorizontalGroup(
 
  218             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  219             .addGroup(layout.createSequentialGroup()
 
  220                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  221                     .addGroup(layout.createSequentialGroup()
 
  223                         .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  224                             .addGroup(layout.createSequentialGroup()
 
  225                                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  226                                     .addComponent(noFatOrphansCheckbox)
 
  227                                     .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
 
  228                                         .addComponent(copyImageCheckbox)
 
  229                                         .addComponent(descLabel))
 
  230                                     .addGroup(layout.createSequentialGroup()
 
  232                                         .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, 
false)
 
  233                                             .addGroup(layout.createSequentialGroup()
 
  234                                                 .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 342, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  235                                                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  236                                                 .addComponent(browseButton, javax.swing.GroupLayout.DEFAULT_SIZE, 92, Short.MAX_VALUE))
 
  237                                             .addGroup(layout.createSequentialGroup()
 
  238                                                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  239                                                     .addComponent(imageWriterErrorLabel)
 
  240                                                     .addComponent(jLabel1)
 
  241                                                     .addComponent(changeDatabasePathCheckbox))
 
  242                                                 .addGap(0, 0, Short.MAX_VALUE)))))
 
  243                                 .addGap(0, 0, Short.MAX_VALUE))
 
  244                             .addGroup(layout.createSequentialGroup()
 
  245                                 .addComponent(timeZoneLabel)
 
  246                                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  247                                 .addComponent(timeZoneComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
 
  248                     .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 488, Short.MAX_VALUE)
 
  249                     .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
 
  250                         .addGap(0, 0, Short.MAX_VALUE)
 
  251                         .addComponent(refreshTablebutton, javax.swing.GroupLayout.PREFERRED_SIZE, 129, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  252                     .addGroup(layout.createSequentialGroup()
 
  253                         .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  254                             .addComponent(diskLabel)
 
  255                             .addComponent(errorLabel))
 
  256                         .addGap(0, 0, Short.MAX_VALUE)))
 
  259         layout.setVerticalGroup(
 
  260             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  261             .addGroup(layout.createSequentialGroup()
 
  262                 .addComponent(diskLabel)
 
  263                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  264                 .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  265                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  266                 .addComponent(refreshTablebutton)
 
  267                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  268                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  269                     .addComponent(timeZoneLabel)
 
  270                     .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  271                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  272                 .addComponent(noFatOrphansCheckbox)
 
  273                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  274                 .addComponent(descLabel)
 
  275                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  276                 .addComponent(copyImageCheckbox)
 
  277                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  278                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
 
  279                     .addComponent(browseButton)
 
  280                     .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  281                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  282                 .addComponent(changeDatabasePathCheckbox)
 
  283                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  284                 .addComponent(jLabel1)
 
  285                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  286                 .addComponent(imageWriterErrorLabel)
 
  287                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  288                 .addComponent(errorLabel)
 
  289                 .addContainerGap(58, Short.MAX_VALUE))
 
  293     private void copyImageCheckboxActionPerformed(java.awt.event.ActionEvent evt) {
 
  294         pathTextField.setEnabled(copyImageCheckbox.isSelected());
 
  295         browseButton.setEnabled(copyImageCheckbox.isSelected());
 
  296         changeDatabasePathCheckbox.setEnabled(copyImageCheckbox.isSelected());
 
  300     private void pathTextFieldKeyReleased(java.awt.event.KeyEvent evt) {
 
  304     private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {
 
  305         String oldText = pathTextField.getText();
 
  307         File currentFile = 
new File(oldText);
 
  308         if ((currentFile.getParentFile() != null) && (currentFile.getParentFile().exists())) {
 
  309             fc.setSelectedFile(currentFile);
 
  312         int retval = fc.showOpenDialog(
this);
 
  313         if (retval == JFileChooser.APPROVE_OPTION) {
 
  314             String path = fc.getSelectedFile().getPath();
 
  315             pathTextField.setText(path);
 
  320     private void refreshTablebuttonActionPerformed(java.awt.event.ActionEvent evt) {
 
  325     private javax.swing.JButton browseButton;
 
  326     private javax.swing.JCheckBox changeDatabasePathCheckbox;
 
  327     private javax.swing.JCheckBox copyImageCheckbox;
 
  328     private javax.swing.JLabel descLabel;
 
  329     private javax.swing.JLabel diskLabel;
 
  330     private javax.swing.JTable diskTable;
 
  331     private javax.swing.JLabel errorLabel;
 
  332     private javax.swing.JLabel imageWriterErrorLabel;
 
  333     private javax.swing.JLabel jLabel1;
 
  334     private javax.swing.JScrollPane jScrollPane1;
 
  335     private javax.swing.JCheckBox noFatOrphansCheckbox;
 
  336     private javax.swing.JTextField pathTextField;
 
  337     private javax.swing.JButton refreshTablebutton;
 
  338     private javax.swing.JComboBox<String> timeZoneComboBox;
 
  339     private javax.swing.JLabel timeZoneLabel;
 
  342     private void fireUpdateEvent() {
 
  344             firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), 
false, 
true);
 
  345         } 
catch (Exception e) {
 
  346             logger.log(Level.SEVERE, 
"LocalDiskPanel listener threw exception", e); 
 
  347             MessageNotifyUtil.Notify.show(NbBundle.getMessage(
this.getClass(), 
"LocalDiskPanel.moduleErr"),
 
  348                     NbBundle.getMessage(
this.getClass(), 
"LocalDiskPanel.moduleErr.msg"),
 
  349                     MessageNotifyUtil.MessageType.ERROR);
 
  358     String getContentPaths() {
 
  359         if (disks.size() > 0) {
 
  360             int selectedRow = diskTable.getSelectedRow();
 
  361             LocalDisk selected = disks.get(selectedRow);
 
  362             return selected.getPath();
 
  368     String getTimeZone() {
 
  369         String tz = timeZoneComboBox.getSelectedItem().toString();
 
  370         return tz.substring(tz.indexOf(
")") + 2).trim();
 
  374     boolean getNoFatOrphans() {
 
  375         return noFatOrphansCheckbox.isSelected();
 
  378     private static String getDefaultImageWriterFolder() {
 
  379         return Paths.get(Case.getCurrentCase().getModuleDirectory(), 
"Image Writer").toString();
 
  382     private void setPotentialImageWriterPath(LocalDisk disk) {
 
  384         File subDirectory = Paths.get(getDefaultImageWriterFolder()).toFile();
 
  385         if (!subDirectory.exists()) {
 
  386             subDirectory.mkdirs();
 
  389         String path = disk.getName();
 
  393         path = path.replaceAll(
"[^0-9A-Za-z _()]", 
""); 
 
  394         if (path.isEmpty() || path.startsWith(
" ")) {
 
  395             path = 
"localDisk" + path;
 
  398         path += 
" " + System.currentTimeMillis();
 
  400         pathTextField.setText(Paths.get(getDefaultImageWriterFolder(), path).toString());
 
  403     private boolean imageWriterPathIsValid() {
 
  404         if ((!copyImageCheckbox.isSelected()) || !(diskTable.getSelectedRow() >= 0 && diskTable.getSelectedRow() < disks.size())) {
 
  405             imageWriterErrorLabel.setVisible(
false);
 
  406             imageWriterErrorLabel.setText(
"");
 
  410         if (pathTextField.getText().isEmpty()) {
 
  411             imageWriterErrorLabel.setVisible(
true);
 
  412             imageWriterErrorLabel.setText(NbBundle.getMessage(
this.getClass(), 
"LocalDiskPanel.imageWriterEmptyPathError.text"));
 
  416         File f = 
new File(pathTextField.getText());
 
  417         if (((f.getParentFile() != null) && (!f.getParentFile().exists()))
 
  418                 || (f.getParentFile() == null)) {
 
  419             imageWriterErrorLabel.setVisible(
true);
 
  420             imageWriterErrorLabel.setText(NbBundle.getMessage(
this.getClass(), 
"LocalDiskPanel.imageWriterDirError.text"));
 
  423         if (f.isDirectory()) {
 
  424             imageWriterErrorLabel.setVisible(
true);
 
  425             imageWriterErrorLabel.setText(NbBundle.getMessage(
this.getClass(), 
"LocalDiskPanel.imageWriterIsDirError.text"));
 
  429             imageWriterErrorLabel.setVisible(
true);
 
  430             imageWriterErrorLabel.setText(NbBundle.getMessage(
this.getClass(), 
"LocalDiskPanel.imageWriterFileExistsError.text"));
 
  433         imageWriterErrorLabel.setVisible(
false);
 
  434         imageWriterErrorLabel.setText(
"");
 
  438     boolean getImageWriterEnabled() {
 
  439         return copyImageCheckbox.isSelected();
 
  442     ImageWriterSettings getImageWriterSettings() {
 
  443         return new ImageWriterSettings(pathTextField.getText(), changeDatabasePathCheckbox.isSelected());
 
  452     boolean validatePanel() {
 
  453         if (!imageWriterPathIsValid()) {
 
  462     public void refreshTable() {
 
  470     public void createTimeZoneList() {
 
  472         String[] ids = SimpleTimeZone.getAvailableIDs();
 
  473         for (String 
id : ids) {
 
  474             TimeZone zone = TimeZone.getTimeZone(
id);
 
  475             int offset = zone.getRawOffset() / 1000;
 
  476             int hour = offset / 3600;
 
  477             int minutes = (offset % 3600) / 60;
 
  478             String item = String.format(
"(GMT%+d:%02d) %s", hour, minutes, 
id); 
 
  489             timeZoneComboBox.addItem(item);
 
  492         TimeZone thisTimeZone = Calendar.getInstance().getTimeZone();
 
  493         int thisOffset = thisTimeZone.getRawOffset() / 1000;
 
  494         int thisHour = thisOffset / 3600;
 
  495         int thisMinutes = (thisOffset % 3600) / 60;
 
  496         String formatted = String.format(
"(GMT%+d:%02d) %s", thisHour, thisMinutes, thisTimeZone.getID()); 
 
  499         timeZoneComboBox.setSelectedItem(formatted);
 
  508         private LocalDiskThread worker = null;
 
  509         private boolean ready = 
false;
 
  510         private volatile boolean loadingDisks = 
false;
 
  513         private final String LOADING = NbBundle.getMessage(this.getClass(), 
"LocalDiskPanel.localDiskModel.loading.msg");
 
  514         private final String NO_DRIVES = NbBundle.getMessage(this.getClass(), 
"LocalDiskPanel.localDiskModel.nodrives.msg");
 
  519             if (loadingDisks && worker != null) {
 
  520                 worker.cancel(
false);
 
  524             errorLabel.setText(
"");
 
  525             diskTable.setEnabled(
false);
 
  529             worker = 
new LocalDiskThread();
 
  535             if (disks.isEmpty()) {
 
  547         @NbBundle.Messages({
"LocalDiskPanel.diskTable.column1.title=Disk Name",
 
  548             "LocalDiskPanel.diskTable.column2.title=Disk Size" 
  553             switch (columnIndex) {
 
  555                     return NbBundle.getMessage(this.getClass(), 
"LocalDiskPanel.diskTable.column1.title");
 
  557                     return NbBundle.getMessage(this.getClass(), 
"LocalDiskPanel.diskTable.column2.title");
 
  576                 if (disks.isEmpty()) {
 
  579                 switch (columnIndex) {
 
  581                         return disks.get(rowIndex).getName();
 
  583                         return disks.get(rowIndex).getReadableSize();
 
  585                         return disks.get(rowIndex).getPath();
 
  593         public void setValueAt(Object aValue, 
int rowIndex, 
int columnIndex) {
 
  611         class LocalDiskThread 
extends SwingWorker<Object, Void> {
 
  614             private List<LocalDisk> physicalDrives = 
new ArrayList<>();
 
  615             private List<LocalDisk> partitions = 
new ArrayList<>();
 
  618             protected Object doInBackground() throws Exception {
 
  620                 physicalDrives = 
new ArrayList<>();
 
  621                 partitions = 
new ArrayList<>();
 
  631             private void displayErrors() {
 
  632                 if (physicalDrives.isEmpty() && partitions.isEmpty()) {
 
  635                                 NbBundle.getMessage(
this.getClass(), 
"LocalDiskPanel.errLabel.disksNotDetected.text"));
 
  636                         errorLabel.setToolTipText(NbBundle.getMessage(
this.getClass(),
 
  637                                 "LocalDiskPanel.errLabel.disksNotDetected.toolTipText"));
 
  640                                 NbBundle.getMessage(
this.getClass(), 
"LocalDiskPanel.errLabel.drivesNotDetected.text"));
 
  641                         errorLabel.setToolTipText(NbBundle.getMessage(
this.getClass(),
 
  642                                 "LocalDiskPanel.errLabel.drivesNotDetected.toolTipText"));
 
  644                     errorLabel.setVisible(
true);
 
  645                     diskTable.setEnabled(
false);
 
  646                 } 
else if (physicalDrives.isEmpty()) {
 
  648                             NbBundle.getMessage(
this.getClass(), 
"LocalDiskPanel.errLabel.someDisksNotDetected.text"));
 
  649                     errorLabel.setToolTipText(NbBundle.getMessage(
this.getClass(),
 
  650                             "LocalDiskPanel.errLabel.someDisksNotDetected.toolTipText"));
 
  651                     errorLabel.setVisible(
true);
 
  656             protected void done() {
 
  659                 } 
catch (CancellationException ex) {
 
  660                     logger.log(Level.INFO, 
"Loading local disks was canceled."); 
 
  661                 } 
catch (InterruptedException ex) {
 
  662                     logger.log(Level.INFO, 
"Loading local disks was interrupted."); 
 
  663                 } 
catch (Exception ex) {
 
  664                     logger.log(Level.SEVERE, 
"Fatal error when loading local disks", ex); 
 
  666                     if (!this.isCancelled()) {
 
  670                         loadingDisks = 
false;
 
  671                         disks = 
new ArrayList<>();
 
  672                         disks.addAll(physicalDrives);
 
  673                         disks.addAll(partitions);
 
  674                         if (disks.size() > 0) {
 
  675                             diskTable.setEnabled(
true);
 
  676                             diskTable.clearSelection();
 
  678                         pathTextField.setText(
"");
 
  683                 diskTable.revalidate();
 
void setValueAt(Object aValue, int rowIndex, int columnIndex)
 
Class<?> getColumnClass(int columnIndex)
 
boolean isCellEditable(int rowIndex, int columnIndex)
 
void removeTableModelListener(TableModelListener l)
 
Object getValueAt(int rowIndex, int columnIndex)
 
synchronized static Logger getLogger(String name)
 
void addTableModelListener(TableModelListener l)
 
String getColumnName(int columnIndex)