19 package org.sleuthkit.autopsy.casemodule;
 
   21 import java.awt.BorderLayout;
 
   22 import java.awt.Color;
 
   23 import java.awt.Component;
 
   25 import java.util.ArrayList;
 
   26 import java.util.Calendar;
 
   27 import java.util.List;
 
   28 import java.util.SimpleTimeZone;
 
   29 import java.util.TimeZone;
 
   30 import java.util.concurrent.CancellationException;
 
   31 import java.util.logging.Level;
 
   32 import javax.swing.ComboBoxModel;
 
   33 import javax.swing.JLabel;
 
   34 import javax.swing.JList;
 
   35 import javax.swing.JPanel;
 
   36 import javax.swing.JSeparator;
 
   37 import javax.swing.ListCellRenderer;
 
   38 import javax.swing.SwingWorker;
 
   39 import javax.swing.border.EmptyBorder;
 
   40 import javax.swing.event.ListDataListener;
 
   41 import org.openide.util.NbBundle;
 
   52 final class LocalDiskPanel 
extends JPanel {
 
   54     private static final Logger logger = Logger.getLogger(LocalDiskPanel.class.getName());
 
   55     private static LocalDiskPanel instance;
 
   56     private List<LocalDisk> disks;
 
   57     private LocalDiskModel model;
 
   58     private boolean enableNext = 
false;
 
   63     public LocalDiskPanel() {
 
   64         this.disks = 
new ArrayList<>();
 
   75     public static synchronized LocalDiskPanel getDefault() {
 
   76         if (instance == null) {
 
   77             instance = 
new LocalDiskPanel();
 
   82     @SuppressWarnings(
"unchecked")
 
   83     private 
void customInit() {
 
   84         model = 
new LocalDiskModel();
 
   85         diskComboBox.setModel(model);
 
   86         diskComboBox.setRenderer(model);
 
   88         errorLabel.setVisible(
false);
 
   89         errorLabel.setText(
"");
 
   90         diskComboBox.setEnabled(
false);
 
   98     @SuppressWarnings(
"unchecked")
 
  100     private 
void initComponents() {
 
  102         diskLabel = 
new javax.swing.JLabel();
 
  103         diskComboBox = 
new javax.swing.JComboBox<>();
 
  104         errorLabel = 
new javax.swing.JLabel();
 
  105         timeZoneLabel = 
new javax.swing.JLabel();
 
  106         timeZoneComboBox = 
new javax.swing.JComboBox<>();
 
  107         noFatOrphansCheckbox = 
new javax.swing.JCheckBox();
 
  108         descLabel = 
new javax.swing.JLabel();
 
  110         setMinimumSize(
new java.awt.Dimension(0, 65));
 
  111         setPreferredSize(
new java.awt.Dimension(485, 65));
 
  113         diskLabel.setFont(diskLabel.getFont().deriveFont(diskLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  114         org.openide.awt.Mnemonics.setLocalizedText(diskLabel, 
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, 
"LocalDiskPanel.diskLabel.text")); 
 
  116         diskComboBox.setFont(diskComboBox.getFont().deriveFont(diskComboBox.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  118         errorLabel.setFont(errorLabel.getFont().deriveFont(errorLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  119         errorLabel.setForeground(
new java.awt.Color(255, 0, 0));
 
  120         org.openide.awt.Mnemonics.setLocalizedText(errorLabel, 
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, 
"LocalDiskPanel.errorLabel.text")); 
 
  122         timeZoneLabel.setFont(timeZoneLabel.getFont().deriveFont(timeZoneLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  123         org.openide.awt.Mnemonics.setLocalizedText(timeZoneLabel, 
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, 
"LocalDiskPanel.timeZoneLabel.text")); 
 
  125         timeZoneComboBox.setFont(timeZoneComboBox.getFont().deriveFont(timeZoneComboBox.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  126         timeZoneComboBox.setMaximumRowCount(30);
 
  128         noFatOrphansCheckbox.setFont(noFatOrphansCheckbox.getFont().deriveFont(noFatOrphansCheckbox.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  129         org.openide.awt.Mnemonics.setLocalizedText(noFatOrphansCheckbox, 
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, 
"LocalDiskPanel.noFatOrphansCheckbox.text")); 
 
  130         noFatOrphansCheckbox.setToolTipText(
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, 
"LocalDiskPanel.noFatOrphansCheckbox.toolTipText")); 
 
  132         descLabel.setFont(descLabel.getFont().deriveFont(descLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  133         org.openide.awt.Mnemonics.setLocalizedText(descLabel, 
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, 
"LocalDiskPanel.descLabel.text")); 
 
  135         javax.swing.GroupLayout layout = 
new javax.swing.GroupLayout(
this);
 
  136         this.setLayout(layout);
 
  137         layout.setHorizontalGroup(
 
  138             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  139             .addGroup(layout.createSequentialGroup()
 
  140                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  141                     .addComponent(diskLabel)
 
  142                     .addComponent(diskComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 345, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  143                     .addComponent(errorLabel)
 
  144                     .addGroup(layout.createSequentialGroup()
 
  145                         .addComponent(timeZoneLabel)
 
  146                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  147                         .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  148                     .addComponent(noFatOrphansCheckbox)
 
  149                     .addGroup(layout.createSequentialGroup()
 
  151                         .addComponent(descLabel)))
 
  152                 .addGap(0, 102, Short.MAX_VALUE))
 
  154         layout.setVerticalGroup(
 
  155             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  156             .addGroup(layout.createSequentialGroup()
 
  157                 .addComponent(diskLabel)
 
  158                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  159                 .addComponent(diskComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  161                 .addComponent(errorLabel)
 
  162                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  163                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  164                     .addComponent(timeZoneLabel)
 
  165                     .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  167                 .addComponent(noFatOrphansCheckbox)
 
  168                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  169                 .addComponent(descLabel)
 
  170                 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 
  174     private javax.swing.JLabel descLabel;
 
  175     private javax.swing.JComboBox<LocalDisk> diskComboBox;
 
  176     private javax.swing.JLabel diskLabel;
 
  177     private javax.swing.JLabel errorLabel;
 
  178     private javax.swing.JCheckBox noFatOrphansCheckbox;
 
  179     private javax.swing.JComboBox<String> timeZoneComboBox;
 
  180     private javax.swing.JLabel timeZoneLabel;
 
  189     public String getContentPaths() {
 
  190         if (disks.size() > 0) {
 
  191             LocalDisk selected = (LocalDisk) diskComboBox.getSelectedItem();
 
  192             return selected.getPath();
 
  202     public void setContentPath(String s) {
 
  203         for (
int i = 0; i < disks.size(); i++) {
 
  204             if (disks.get(i).getPath().equals(s)) {
 
  205                 diskComboBox.setSelectedIndex(i);
 
  210     public String getTimeZone() {
 
  211         String tz = timeZoneComboBox.getSelectedItem().toString();
 
  212         return tz.substring(tz.indexOf(
")") + 2).trim();
 
  216     boolean getNoFatOrphans() {
 
  217         return noFatOrphansCheckbox.isSelected();
 
  227     public boolean validatePanel() {
 
  232     public void reset() {
 
  241     public void select() {
 
  242         diskComboBox.requestFocusInWindow();
 
  251     public void createTimeZoneList() {
 
  253         String[] ids = SimpleTimeZone.getAvailableIDs();
 
  254         for (String 
id : ids) {
 
  255             TimeZone zone = TimeZone.getTimeZone(
id);
 
  256             int offset = zone.getRawOffset() / 1000;
 
  257             int hour = offset / 3600;
 
  258             int minutes = (offset % 3600) / 60;
 
  259             String item = String.format(
"(GMT%+d:%02d) %s", hour, minutes, 
id); 
 
  270             timeZoneComboBox.addItem(item);
 
  273         TimeZone thisTimeZone = Calendar.getInstance().getTimeZone();
 
  274         int thisOffset = thisTimeZone.getRawOffset() / 1000;
 
  275         int thisHour = thisOffset / 3600;
 
  276         int thisMinutes = (thisOffset % 3600) / 60;
 
  277         String formatted = String.format(
"(GMT%+d:%02d) %s", thisHour, thisMinutes, thisTimeZone.getID()); 
 
  280         timeZoneComboBox.setSelectedItem(formatted);
 
  283     @SuppressWarnings(
"rawtypes")
 
  288         private boolean ready = 
false;
 
  290         private volatile boolean loadingDisks = 
false;
 
  292         List<LocalDisk> physicalDrives = 
new ArrayList<>();
 
  293         List<LocalDisk> partitions = 
new ArrayList<>();
 
  296         private String LOADING = NbBundle.getMessage(this.getClass(), 
"LocalDiskPanel.localDiskModel.loading.msg");
 
  297         private String NO_DRIVES = NbBundle.getMessage(this.getClass(), 
"LocalDiskPanel.localDiskModel.nodrives.msg");
 
  299         LocalDiskThread worker = null;
 
  304             if (loadingDisks && worker != null) {
 
  305                 worker.cancel(
false);
 
  309             errorLabel.setText(
"");
 
  310             disks = 
new ArrayList<>();
 
  311             physicalDrives = 
new ArrayList<>();
 
  312             partitions = 
new ArrayList<>();
 
  313             diskComboBox.setEnabled(
false);
 
  318             worker = 
new LocalDiskThread();
 
  331                 } 
catch (Exception e) {
 
  332                     logger.log(Level.SEVERE, 
"LocalDiskPanel listener threw exception", e); 
 
  334                             NbBundle.getMessage(
this.getClass(), 
"LocalDiskPanel.moduleErr.msg"),
 
  343                 if (disks.isEmpty()) {
 
  355                 if (disks.isEmpty()) {
 
  367                 if (disks.isEmpty()) {
 
  370                 return disks.get(index);
 
  384         @SuppressWarnings(
"rawtypes")
 
  387             JPanel panel = 
new JPanel(
new BorderLayout());
 
  388             JLabel label = 
new JLabel();
 
  389             if ((index == physicalDrives.size() - 1) && (physicalDrives.size() > 0)) {
 
  390                 panel.add(
new JSeparator(JSeparator.HORIZONTAL), BorderLayout.SOUTH);
 
  394                 label.setBackground(list.getSelectionBackground());
 
  395                 label.setForeground(list.getSelectionForeground());
 
  397                 label.setBackground(list.getBackground());
 
  398                 label.setForeground(list.getForeground());
 
  402                 String localDiskString = value.toString();
 
  403                 label.setText(value.toString());
 
  404                 if ((localDiskString.equals(LOADING)) || (localDiskString.equals(NO_DRIVES))) {
 
  405                     label.setFont(label.getFont().deriveFont(Font.ITALIC));
 
  406                     label.setBackground(Color.GRAY);
 
  409             label.setOpaque(
true);
 
  410             label.setBorder(
new EmptyBorder(2, 2, 2, 2));
 
  412             panel.add(label, BorderLayout.CENTER);
 
  416         class LocalDiskThread 
extends SwingWorker<Object, Void> {
 
  421             protected Object doInBackground() throws Exception {
 
  429             private void displayErrors() {
 
  430                 if (physicalDrives.isEmpty() && partitions.isEmpty()) {
 
  433                                 NbBundle.getMessage(
this.getClass(), 
"LocalDiskPanel.errLabel.disksNotDetected.text"));
 
  434                         errorLabel.setToolTipText(NbBundle.getMessage(
this.getClass(),
 
  435                                 "LocalDiskPanel.errLabel.disksNotDetected.toolTipText"));
 
  438                                 NbBundle.getMessage(
this.getClass(), 
"LocalDiskPanel.errLabel.drivesNotDetected.text"));
 
  439                         errorLabel.setToolTipText(NbBundle.getMessage(
this.getClass(),
 
  440                                 "LocalDiskPanel.errLabel.drivesNotDetected.toolTipText"));
 
  442                     diskComboBox.setEnabled(
false);
 
  443                 } 
else if (physicalDrives.isEmpty()) {
 
  445                             NbBundle.getMessage(
this.getClass(), 
"LocalDiskPanel.errLabel.someDisksNotDetected.text"));
 
  446                     errorLabel.setToolTipText(NbBundle.getMessage(
this.getClass(),
 
  447                             "LocalDiskPanel.errLabel.someDisksNotDetected.toolTipText"));
 
  452             protected void done() {
 
  455                 } 
catch (CancellationException ex) {
 
  456                     logger.log(Level.INFO, 
"Loading local disks was canceled, which should not be possible."); 
 
  457                 } 
catch (InterruptedException ex) {
 
  458                     logger.log(Level.INFO, 
"Loading local disks was interrupted."); 
 
  459                 } 
catch (Exception ex) {
 
  460                     logger.log(Level.SEVERE, 
"Fatal error when loading local disks", ex); 
 
  462                     if (!this.isCancelled()) {
 
  467                         loadingDisks = 
false;
 
  469                         disks.addAll(physicalDrives);
 
  470                         disks.addAll(partitions);
 
  472                         if (disks.size() > 0) {
 
  473                             diskComboBox.setEnabled(
true);
 
  474                             diskComboBox.setSelectedIndex(0);
 
  478                         logger.log(Level.INFO, 
"Loading local disks was canceled, which should not be possible."); 
 
void setSelectedItem(Object anItem)
void addListDataListener(ListDataListener l)
Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
Object getElementAt(int index)
synchronized static Logger getLogger(String name)
static void show(String title, String message, MessageType type, ActionListener actionListener)
void removeListDataListener(ListDataListener l)