/* * Autopsy Forensic Browser * * Copyright 2015 Basis Technology Corp. * Contact: carrier <at> sleuthkit <dot> org * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sleuthkit.autopsy.experimental.autoingest; import java.awt.Color; import java.awt.Cursor; import java.awt.Desktop; import java.awt.EventQueue; import java.awt.Font; import java.io.File; import java.nio.file.Paths; import javax.swing.ImageIcon; import javax.swing.JFileChooser; import javax.swing.JTextField; import org.openide.util.ImageUtilities; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.core.RuntimeProperties; import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.core.UserPreferencesException; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.CaseDbConnectionInfo; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; import java.util.logging.Level; import org.sleuthkit.autopsy.experimental.configuration.AutoIngestUserPreferences; import static org.sleuthkit.autopsy.experimental.configuration.AutoIngestUserPreferences.SelectedMode.AUTOMATED; /** * This panel shows up in a tab pane next to the copy files panel for the * automated ingest copy node. * */ public class CaseImportPanel extends javax.swing.JPanel implements ImportDoneCallback { private final CaseImportPanelController controller; private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(CaseImportPanel.class.getName()); private Thread ongoingImport; // used to interrupt thread if we need to private final JFileChooser caseSourceFolderChooser = new JFileChooser(); private final JFileChooser imageSourceFolderChooser = new JFileChooser(); private CaseDbConnectionInfo db; private final ImageIcon goodDatabaseCredentials; private final ImageIcon badDatabaseCredentials; private boolean canTalkToDb = false; private boolean copyImagesState = true; private boolean deleteImagesState = false; private static final String MULTI_USER_SETTINGS_MUST_BE_ENABLED = NbBundle.getMessage(CaseImportPanel.class, "CaseImportPanel.validationErrMsg.MUdisabled"); private static final String AIM_MUST_BE_ENABLED = NbBundle.getMessage(CaseImportPanel.class, "CaseImportPanel.validationErrMsg.AIMdisabled"); // Used to specify which notification area should be upated private enum NotificationLabel { INPUT, OUTPUT, BOTTOM, PROGRESS } /** * Creates new panel CaseImportPanel */ public CaseImportPanel(CaseImportPanelController theController) { controller = theController; initComponents(); badDatabaseCredentials = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/experimental/images/warning16.png", false)); //NON-NLS goodDatabaseCredentials = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/experimental/images/tick.png", false)); //NON-NLS } /** * Validate current panel settings. */ boolean valid() { // Nothing to validate for case import panel as far as Netbeans Tools/Options controller is concerned return true; } /** * Store current panel settings. */ void store() { // Nothing to store for case import panel as far as Netbeans Tools/Options controller is concerned } /** * Load data. */ final void load() { // Multi user mode must be enabled. This is required to make sure database credentials are set. // Also, "join auto ingest cluster" must be selected and we need to be in automated ingest mode. // This is required to make sure "shared images" and "shared results" folders are set if (!UserPreferences.getIsMultiUserModeEnabled()) { tbOops.setText(MULTI_USER_SETTINGS_MUST_BE_ENABLED); return; } else if (RuntimeProperties.coreComponentsAreActive()) { tbOops.setText(AIM_MUST_BE_ENABLED); return; } else { tbOops.setText(""); } // Note: we used to store input folders in persistent storage but it is not done any more for some reason... caseSourceFolderChooser.setCurrentDirectory(caseSourceFolderChooser.getFileSystemView().getParentDirectory(new File("C:\\"))); //NON-NLS caseSourceFolderChooser.setAcceptAllFileFilterUsed(false); caseSourceFolderChooser.setDialogTitle(NbBundle.getMessage(CaseImportPanel.class, "CaseImportPanel.ChooseCase")); caseSourceFolderChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); imageSourceFolderChooser.setCurrentDirectory(imageSourceFolderChooser.getFileSystemView().getParentDirectory(new File("C:\\"))); //NON-NLS imageSourceFolderChooser.setAcceptAllFileFilterUsed(false); imageSourceFolderChooser.setDialogTitle(NbBundle.getMessage(CaseImportPanel.class, "CaseImportPanel.ChooseSource")); imageSourceFolderChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); cbCopyImages.setSelected(true); cbDeleteCase.setSelected(false); picDbStatus.setText(""); //NON-NLS tbDeleteWarning.setText(""); //NON-NLS tbInputNotification.setText(""); //NON-NLS tbOutputNotification.setText(""); //NON-NLS tbBottomNotification.setText(""); //NON-NLS pbShowProgress.setStringPainted(true); pbShowProgress.setForeground(new Color(51, 153, 255)); pbShowProgress.setString(""); //NON-NLS showDbStatus(); handleAutoModeInputs(); } void handleAutoModeInputs() { String caseDestinationResult = ""; String output = AutoIngestUserPreferences.getAutoModeResultsFolder(); if (output.isEmpty() || !(new File(output).exists())) { setNotificationText(NotificationLabel.OUTPUT, NbBundle.getMessage(CaseImportPanel.class, "CaseImportPanel.BadCaseDestinationFolder"), false); } else { tbCaseDestination.setText(output); caseDestinationResult = ""; } String imageDestinationResult = ""; String imageFolder = AutoIngestUserPreferences.getAutoModeImageFolder(); if (imageFolder.isEmpty() || !(new File(imageFolder).exists())) { setNotificationText(NotificationLabel.OUTPUT, NbBundle.getMessage(CaseImportPanel.class, "CaseImportPanel.BadImageDestinationFolder"), false); } else { tbImageDestination.setText(imageFolder); imageDestinationResult = ""; } String result = caseDestinationResult; if (result.isEmpty()) { result = imageDestinationResult; } setNotificationText(NotificationLabel.OUTPUT, result, false); } /** * Set status pictures to show if the database credentials are good or bad */ private void showDbStatus() { try { db = UserPreferences.getDatabaseConnectionInfo(); } catch (UserPreferencesException ex) { logger.log(Level.SEVERE, "Error accessing case database connection info", ex); //NON-NLS setDbConnectionStatus(false, badDatabaseCredentials, NbBundle.getMessage(CaseImportPanel.class, "CaseImportPanel.DatabaseNotConnected")); return; } try { SleuthkitCase.tryConnect(db); setDbConnectionStatus(true, goodDatabaseCredentials, NbBundle.getMessage(CaseImportPanel.class, "CaseImportPanel.DatabaseConnected")); } catch (TskCoreException ex) { setDbConnectionStatus(false, badDatabaseCredentials, NbBundle.getMessage(CaseImportPanel.class, "CaseImportPanel.DatabaseNotConnected")); logger.log(Level.SEVERE, "Unable to communicate with PostgreSQL: {0}", ex.getMessage()); } } private void setDbConnectionStatus(boolean canConnect, ImageIcon credentials, String text) { canTalkToDb = canConnect; picDbStatus.setIcon(credentials); picDbStatus.setText(text); } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { lbDbConnection = new javax.swing.JLabel(); picDbStatus = new javax.swing.JLabel(); lbCaseDestination = new javax.swing.JLabel(); lbCaseSource = new javax.swing.JLabel(); lbCaption = new javax.swing.JLabel(); lbImageDestination = new javax.swing.JLabel(); lbImageSource = new javax.swing.JLabel(); bnStart = new javax.swing.JButton(); bnCancel = new javax.swing.JButton(); bnShowLog = new javax.swing.JButton(); bnBrowseCaseSource = new javax.swing.JButton(); bnBrowseImageSource = new javax.swing.JButton(); pbShowProgress = new javax.swing.JProgressBar(); tbCaseSource = new javax.swing.JTextField(); tbCaseDestination = new javax.swing.JTextField(); tbImageDestination = new javax.swing.JTextField(); tbBottomNotification = new javax.swing.JTextField(); tbImageSource = new javax.swing.JTextField(); cbCopyImages = new javax.swing.JCheckBox(); cbDeleteCase = new javax.swing.JCheckBox(); lbProgressBar = new javax.swing.JLabel(); tbInputNotification = new javax.swing.JTextField(); tbOutputNotification = new javax.swing.JTextField(); tbDeleteWarning = new javax.swing.JTextField(); tbOops = new javax.swing.JTextField(); setMinimumSize(new java.awt.Dimension(830, 240)); lbDbConnection.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N lbDbConnection.setText("Database"); lbDbConnection.setToolTipText("Set database credentials via 'Options'"); lbDbConnection.setVerticalAlignment(javax.swing.SwingConstants.BOTTOM); lbDbConnection.setFocusable(false); picDbStatus.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N picDbStatus.setLabelFor(lbDbConnection); picDbStatus.setText("Database Status"); picDbStatus.setVerticalAlignment(javax.swing.SwingConstants.BOTTOM); picDbStatus.setFocusable(false); lbCaseDestination.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N lbCaseDestination.setText("Case Destination"); lbCaseDestination.setFocusable(false); lbCaseSource.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N lbCaseSource.setLabelFor(lbCaseSource); lbCaseSource.setText("Case Source"); lbCaseSource.setVerticalAlignment(javax.swing.SwingConstants.BOTTOM); lbCaseSource.setFocusable(false); lbCaption.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N lbCaption.setText("Import single-user cases to multi-user cases"); lbImageDestination.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N lbImageDestination.setText("Image Destination"); lbImageDestination.setFocusable(false); lbImageSource.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N lbImageSource.setText("Image Source"); lbImageSource.setFocusable(false); bnStart.setText("Start"); bnStart.setEnabled(false); bnStart.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { bnStartActionPerformed(evt); } }); bnCancel.setText("Cancel"); bnCancel.setEnabled(false); bnCancel.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { bnCancelActionPerformed(evt); } }); bnShowLog.setText("Show Log"); bnShowLog.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { bnShowLogActionPerformed(evt); } }); bnBrowseCaseSource.setText("Browse"); bnBrowseCaseSource.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { bnBrowseCaseSourceActionPerformed(evt); } }); bnBrowseImageSource.setText("Browse"); bnBrowseImageSource.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { bnBrowseImageSourceActionPerformed(evt); } }); pbShowProgress.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N pbShowProgress.setToolTipText(""); pbShowProgress.setFocusable(false); pbShowProgress.setMaximumSize(new java.awt.Dimension(32767, 16)); pbShowProgress.setPreferredSize(new java.awt.Dimension(146, 16)); tbCaseSource.setEditable(false); tbCaseSource.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N tbCaseSource.setToolTipText("Press \"Browse\" to select the case source folder."); tbCaseSource.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(153, 153, 153), 1, true)); tbCaseSource.setFocusable(false); tbCaseDestination.setEditable(false); tbCaseDestination.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N tbCaseDestination.setToolTipText("The case destination folder. Press \"Options\" and edit \"Shared Results Folder\" to change this. Any imported cases will be stored in this folder."); tbCaseDestination.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(153, 153, 153), 1, true)); tbCaseDestination.setFocusable(false); tbImageDestination.setEditable(false); tbImageDestination.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N tbImageDestination.setToolTipText("This is the Image folder. Press \"Options\" and edit \"Shared Images Folder\" to change this. Any input images will be copied to this folder during import."); tbImageDestination.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(153, 153, 153), 1, true)); tbImageDestination.setFocusable(false); tbBottomNotification.setEditable(false); tbBottomNotification.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N tbBottomNotification.setHorizontalAlignment(javax.swing.JTextField.RIGHT); tbBottomNotification.setText("tbNotification"); tbBottomNotification.setToolTipText("Shows notifications"); tbBottomNotification.setBorder(null); tbBottomNotification.setFocusable(false); tbImageSource.setEditable(false); tbImageSource.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N tbImageSource.setToolTipText("Press \"Browse\" to select the image source folder."); tbImageSource.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(153, 153, 153), 1, true)); tbImageSource.setFocusable(false); cbCopyImages.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N cbCopyImages.setText("Copy images"); cbCopyImages.addChangeListener(new javax.swing.event.ChangeListener() { public void stateChanged(javax.swing.event.ChangeEvent evt) { cbCopyImagesStateChanged(evt); } }); cbCopyImages.addPropertyChangeListener(new java.beans.PropertyChangeListener() { public void propertyChange(java.beans.PropertyChangeEvent evt) { cbCopyImagesPropertyChange(evt); } }); cbDeleteCase.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N cbDeleteCase.setText("Delete original case"); cbDeleteCase.addPropertyChangeListener(new java.beans.PropertyChangeListener() { public void propertyChange(java.beans.PropertyChangeEvent evt) { cbDeleteCasePropertyChange(evt); } }); lbProgressBar.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N lbProgressBar.setText("Progress"); tbInputNotification.setEditable(false); tbInputNotification.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N tbInputNotification.setHorizontalAlignment(javax.swing.JTextField.RIGHT); tbInputNotification.setText("Input box"); tbInputNotification.setBorder(null); tbOutputNotification.setEditable(false); tbOutputNotification.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N tbOutputNotification.setHorizontalAlignment(javax.swing.JTextField.RIGHT); tbOutputNotification.setText("Output box"); tbOutputNotification.setBorder(null); tbDeleteWarning.setEditable(false); tbDeleteWarning.setText("delete warning"); tbDeleteWarning.setBorder(null); tbOops.setEditable(false); tbOops.setFont(tbOops.getFont().deriveFont(tbOops.getFont().getStyle() | java.awt.Font.BOLD, 12)); tbOops.setForeground(new java.awt.Color(255, 0, 0)); tbOops.setBorder(null); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGap(41, 41, 41) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(lbImageSource, javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(lbCaseSource, javax.swing.GroupLayout.Alignment.TRAILING)) .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(tbCaseSource) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(bnBrowseCaseSource, javax.swing.GroupLayout.PREFERRED_SIZE, 99, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(tbImageSource) .addGroup(layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) .addComponent(tbInputNotification, javax.swing.GroupLayout.PREFERRED_SIZE, 527, javax.swing.GroupLayout.PREFERRED_SIZE))) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(bnBrowseImageSource, javax.swing.GroupLayout.PREFERRED_SIZE, 99, javax.swing.GroupLayout.PREFERRED_SIZE)))) .addGroup(layout.createSequentialGroup() .addGap(37, 37, 37) .addComponent(lbCaption) .addGap(35, 35, 35) .addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, 465, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 0, Short.MAX_VALUE)) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(layout.createSequentialGroup() .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(tbOutputNotification, javax.swing.GroupLayout.PREFERRED_SIZE, 495, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(tbBottomNotification, javax.swing.GroupLayout.PREFERRED_SIZE, 391, javax.swing.GroupLayout.PREFERRED_SIZE))) .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(lbCaseDestination, javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(lbImageDestination, javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(lbDbConnection, javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(lbProgressBar, javax.swing.GroupLayout.Alignment.TRAILING)) .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(tbCaseDestination) .addComponent(tbImageDestination) .addComponent(pbShowProgress, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() .addComponent(bnStart, javax.swing.GroupLayout.PREFERRED_SIZE, 99, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(bnCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 99, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(bnShowLog, javax.swing.GroupLayout.PREFERRED_SIZE, 99, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(cbCopyImages) .addComponent(picDbStatus) .addGroup(layout.createSequentialGroup() .addComponent(cbDeleteCase) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(tbDeleteWarning, javax.swing.GroupLayout.PREFERRED_SIZE, 478, javax.swing.GroupLayout.PREFERRED_SIZE))) .addGap(0, 11, Short.MAX_VALUE))))) .addGap(105, 105, 105))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(lbCaption) .addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) .addComponent(bnBrowseCaseSource) .addComponent(tbCaseSource, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(lbCaseSource)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) .addComponent(bnBrowseImageSource) .addComponent(tbImageSource, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(lbImageSource)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(cbCopyImages) .addComponent(tbInputNotification, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(cbDeleteCase) .addComponent(tbDeleteWarning, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(35, 35, 35) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) .addComponent(tbCaseDestination, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(lbCaseDestination)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) .addComponent(tbImageDestination, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(lbImageDestination)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(tbOutputNotification, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(9, 9, 9) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(lbDbConnection) .addComponent(picDbStatus)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) .addComponent(pbShowProgress, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(lbProgressBar)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(bnShowLog) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(bnStart) .addComponent(bnCancel))) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(tbBottomNotification, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap(172, Short.MAX_VALUE)) ); }// </editor-fold>//GEN-END:initComponents /** * Handles pressing the "Start" button * * @param evt */ private void bnStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnStartActionPerformed showDbStatus(); if (canTalkToDb) { setNotificationText(NotificationLabel.PROGRESS, NbBundle.getMessage(CaseImportPanel.class, "CaseImportPanel.ImportingCases"), true); SingleUserCaseImporter caseImporter = new SingleUserCaseImporter( tbImageSource.getText(), tbCaseSource.getText(), tbImageDestination.getText(), tbCaseDestination.getText(), cbCopyImages.isSelected(), cbDeleteCase.isSelected(), this); pbShowProgress.setIndeterminate(true); ongoingImport = new Thread(caseImporter); setButtonsForJobRunning(true); ongoingImport.start(); } else { bnStart.setEnabled(false); } }//GEN-LAST:event_bnStartActionPerformed /** * Allows bulk-setting the button enabled states. * * @param setting true if we are currently processing an import job, false * otherwise */ void setButtonsForJobRunning(boolean setting) { bnBrowseCaseSource.setEnabled(!setting); bnBrowseImageSource.setEnabled(!setting); cbCopyImages.setEnabled(!setting); cbDeleteCase.setEnabled(!setting); bnStart.setEnabled(!setting); bnCancel.setEnabled(setting); } /** * Handles pressing the Cancel button * * @param evt */ private void bnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnCancelActionPerformed if (ongoingImport != null) { setNotificationText(NotificationLabel.PROGRESS, NbBundle.getMessage(CaseImportPanel.class, "CaseImportPanel.Cancelling"), false); ongoingImport.interrupt(); } }//GEN-LAST:event_bnCancelActionPerformed /** * Handles pressing the Browse for case source folder button * * @param evt */ private void bnBrowseCaseSourceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnBrowseCaseSourceActionPerformed int returnVal = caseSourceFolderChooser.showOpenDialog(this); if (returnVal == JFileChooser.APPROVE_OPTION) { validateSourceFields(); } }//GEN-LAST:event_bnBrowseCaseSourceActionPerformed /** * Show user information about status of source fields, hierarchically. */ private void validateSourceFields() { String caseSourceResult = ""; File selectedFolder = caseSourceFolderChooser.getSelectedFile(); if (selectedFolder == null || !selectedFolder.exists()) { caseSourceResult = NbBundle.getMessage(CaseImportPanel.class, "CaseImportPanel.BadCaseSourceFolder"); tbCaseSource.setText(""); } else { caseSourceResult = NbBundle.getMessage(CaseImportPanel.class, "CaseImportPanel.Blank"); caseSourceFolderChooser.setCurrentDirectory(selectedFolder); tbCaseSource.setText(selectedFolder.toString()); } String caseImagesResult = ""; if (cbCopyImages.isSelected()) { selectedFolder = imageSourceFolderChooser.getSelectedFile(); if (selectedFolder == null || !selectedFolder.exists()) { caseImagesResult = NbBundle.getMessage(CaseImportPanel.class, "CaseImportPanel.BadImageSourceFolder"); tbImageSource.setText(""); //NON-NLS } else { if (tbInputNotification.getText().isEmpty()) { caseImagesResult = NbBundle.getMessage(CaseImportPanel.class, "CaseImportPanel.Blank"); } imageSourceFolderChooser.setCurrentDirectory(selectedFolder); tbImageSource.setText(selectedFolder.toString()); } } String result = caseSourceResult; if (result.isEmpty()) { result = caseImagesResult; } setNotificationText(NotificationLabel.INPUT, result, false); enableStartButton(); } /** * Handles pressing the Show Log button * * @param evt */ private void bnShowLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnShowLogActionPerformed try { File logFile = Paths.get(tbCaseDestination.getText(), SingleUserCaseImporter.CASE_IMPORT_LOG_FILE).toFile(); setNotificationText(NotificationLabel.BOTTOM, "", false); //NON-NLS Desktop.getDesktop().edit(logFile); } catch (Exception ex) { setNotificationText(NotificationLabel.BOTTOM, NbBundle.getMessage(CaseImportPanel.class, "CaseImportPanel.CannotOpenLog"), false); } }//GEN-LAST:event_bnShowLogActionPerformed /** * Handles pressing the Browse for image source folder button * * @param evt */ private void bnBrowseImageSourceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnBrowseImageSourceActionPerformed int returnVal = imageSourceFolderChooser.showOpenDialog(this); if (returnVal == JFileChooser.APPROVE_OPTION) { validateSourceFields(); } }//GEN-LAST:event_bnBrowseImageSourceActionPerformed private void cbCopyImagesPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_cbCopyImagesPropertyChange }//GEN-LAST:event_cbCopyImagesPropertyChange private void cbDeleteCasePropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_cbDeleteCasePropertyChange if (deleteImagesState != cbDeleteCase.isSelected()) { deleteImagesState = cbDeleteCase.isSelected(); if (cbDeleteCase.isSelected()) { tbDeleteWarning.setForeground(Color.RED); tbDeleteWarning.setText(NbBundle.getMessage(CaseImportPanel.class, "CaseImportPanel.DeleteWarning")); } else { // USE BUNDLE tbDeleteWarning.setText(""); } } }//GEN-LAST:event_cbDeleteCasePropertyChange private void cbCopyImagesStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_cbCopyImagesStateChanged // Enable or disable the image folder entries // this gets notified of mouseovers and such, so check that it actually // changed before changing the state of UI components if (copyImagesState != cbCopyImages.isSelected()) { copyImagesState = cbCopyImages.isSelected(); if (copyImagesState) { tbImageSource.setEnabled(true); tbImageDestination.setEnabled(true); bnBrowseImageSource.setEnabled(true); } else { tbImageSource.setEnabled(false); tbImageDestination.setEnabled(false); bnBrowseImageSource.setEnabled(false); } validateSourceFields(); } }//GEN-LAST:event_cbCopyImagesStateChanged /** * Enables the start button if all input is in order, disables it otherwise */ private void enableStartButton() { if (UserPreferences.getIsMultiUserModeEnabled() && AutoIngestUserPreferences.getJoinAutoModeCluster() && (! RuntimeProperties.coreComponentsAreActive()) && !tbCaseSource.getText().isEmpty() && !tbCaseDestination.getText().isEmpty() && canTalkToDb == true && (!cbCopyImages.isSelected() || (!tbImageSource.getText().isEmpty() && !tbImageDestination.getText().isEmpty()))) { bnStart.setEnabled(true); } else { bnStart.setEnabled(false); } } /** * Allows setting the notification text outside the EDT. * * @param position the label we intend to set * @param text The text to set * @param okay True if there was no issue, false otherwise. Sets text * color. */ private void setNotificationText(final NotificationLabel position, final String text, final boolean okay) { EventQueue.invokeLater(() -> { if (position != NotificationLabel.PROGRESS) { JTextField textField; if (position == NotificationLabel.INPUT) { textField = tbInputNotification; } else if (position == NotificationLabel.OUTPUT) { textField = tbOutputNotification; } else { textField = tbBottomNotification; } textField.setText(text); if (okay) { Font font = textField.getFont(); textField.setFont(font.deriveFont(Font.BOLD)); textField.setForeground(Color.BLACK); } else { Font font = textField.getFont(); textField.setFont(font.deriveFont(Font.PLAIN)); textField.setForeground(Color.RED); } } else { pbShowProgress.setString(text); if (okay) { pbShowProgress.setForeground(new Color(51, 153, 255)); } else { pbShowProgress.setForeground(Color.RED); } } }); } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton bnBrowseCaseSource; private javax.swing.JButton bnBrowseImageSource; private javax.swing.JButton bnCancel; private javax.swing.JButton bnShowLog; private javax.swing.JButton bnStart; private javax.swing.JCheckBox cbCopyImages; private javax.swing.JCheckBox cbDeleteCase; private javax.swing.JLabel lbCaption; private javax.swing.JLabel lbCaseDestination; private javax.swing.JLabel lbCaseSource; private javax.swing.JLabel lbDbConnection; private javax.swing.JLabel lbImageDestination; private javax.swing.JLabel lbImageSource; private javax.swing.JLabel lbProgressBar; private javax.swing.JProgressBar pbShowProgress; private javax.swing.JLabel picDbStatus; private javax.swing.JTextField tbBottomNotification; private javax.swing.JTextField tbCaseDestination; private javax.swing.JTextField tbCaseSource; private javax.swing.JTextField tbDeleteWarning; private javax.swing.JTextField tbImageDestination; private javax.swing.JTextField tbImageSource; private javax.swing.JTextField tbInputNotification; private javax.swing.JTextField tbOops; private javax.swing.JTextField tbOutputNotification; // End of variables declaration//GEN-END:variables /** * This method is called by the import thread as it is finishing. * * @param result true if the entire import was successful, false * otherwise * @param resultString the text string to show the user */ @Override public void importDoneCallback(boolean result, String resultString) { if (resultString == null || resultString.isEmpty()) { pbShowProgress.setIndeterminate(false); pbShowProgress.setValue(100); if (result) { setNotificationText(NotificationLabel.PROGRESS, NbBundle.getMessage(CaseImportPanel.class, "CaseImportPanel.Complete"), true); } else { setNotificationText(NotificationLabel.PROGRESS, NbBundle.getMessage(CaseImportPanel.class, "CaseImportPanel.Error"), result); } } else { pbShowProgress.setIndeterminate(false); if (result == true) { pbShowProgress.setValue(0); } else { pbShowProgress.setValue(100); } setNotificationText(NotificationLabel.PROGRESS, resultString, result); } setButtonsForJobRunning(false); ongoingImport = null; showDbStatus(); } }