19 package org.sleuthkit.autopsy.centralrepository.optionspanel;
21 import java.awt.Color;
22 import java.awt.Cursor;
24 import java.io.IOException;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.logging.Level;
28 import javax.swing.JDialog;
29 import javax.swing.JFileChooser;
30 import javax.swing.JFrame;
31 import javax.swing.JOptionPane;
32 import javax.swing.JTextField;
33 import javax.swing.SwingUtilities;
34 import javax.swing.event.DocumentEvent;
35 import javax.swing.event.DocumentListener;
36 import javax.swing.filechooser.FileFilter;
37 import org.netbeans.spi.options.OptionsPanelController;
38 import org.openide.util.NbBundle.Messages;
39 import org.openide.windows.WindowManager;
71 @Messages({
"EamDbSettingsDialog.title.text=Central Repository Database Configuration",
72 "EamDbSettingsDialog.lbSingleUserSqLite.text=SQLite should only be used by one examiner at a time.",
73 "EamDbSettingsDialog.lbDatabaseType.text=Database Type :",
74 "EamDbSettingsDialog.fcDatabasePath.title=Select location for central_repository.db"})
77 super((JFrame) WindowManager.getDefault().getMainWindow(),
78 Bundle.EamDbSettingsDialog_title_text(),
81 textBoxes =
new ArrayList<>();
91 fcDatabasePath.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
93 fcDatabasePath.setDialogTitle(Bundle.EamDbSettingsDialog_fcDatabasePath_title());
96 public boolean accept(File pathname) {
97 if (pathname.isDirectory()) {
99 }
else if (pathname.getName().toLowerCase().equals((CENTRAL_REPO_DB_NAME + CENTRAL_REPO_SQLITE_EXT).toLowerCase())) {
107 public String getDescription() {
108 return "Directories and central repository databases";
123 @SuppressWarnings(
"unchecked")
130 bnCancel =
new javax.swing.JButton();
131 bnOk =
new javax.swing.JButton();
138 lbPort =
new javax.swing.JLabel();
139 tbDbPort =
new javax.swing.JTextField();
149 filler1 =
new javax.swing.Box.Filler(
new java.awt.Dimension(0, 0),
new java.awt.Dimension(0, 0),
new java.awt.Dimension(0, 32767));
151 setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
154 bnCancel.addActionListener(
new java.awt.event.ActionListener() {
155 public void actionPerformed(java.awt.event.ActionEvent evt) {
160 org.openide.awt.Mnemonics.setLocalizedText(
bnOk,
org.openide.util.NbBundle.getMessage(
EamDbSettingsDialog.class,
"EamDbSettingsDialog.bnOk.text"));
161 bnOk.addActionListener(
new java.awt.event.ActionListener() {
162 public void actionPerformed(java.awt.event.ActionEvent evt) {
167 javax.swing.GroupLayout pnButtonsLayout =
new javax.swing.GroupLayout(
pnButtons);
169 pnButtonsLayout.setHorizontalGroup(
170 pnButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
171 .addGroup(pnButtonsLayout.createSequentialGroup()
172 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
178 pnButtonsLayout.setVerticalGroup(
179 pnButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
180 .addGroup(pnButtonsLayout.createSequentialGroup()
182 .addGroup(pnButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
197 public void actionPerformed(java.awt.event.ActionEvent evt) {
204 org.openide.awt.Mnemonics.setLocalizedText(
lbPort,
org.openide.util.NbBundle.getMessage(
EamDbSettingsDialog.class,
"EamDbSettingsDialog.lbPort.text"));
211 cbDatabaseType.addActionListener(
new java.awt.event.ActionListener() {
212 public void actionPerformed(java.awt.event.ActionEvent evt) {
225 javax.swing.GroupLayout pnSQLiteSettingsLayout =
new javax.swing.GroupLayout(
pnSQLiteSettings);
227 pnSQLiteSettingsLayout.setHorizontalGroup(
228 pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
229 .addGroup(pnSQLiteSettingsLayout.createSequentialGroup()
231 .addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
236 .addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING,
false)
237 .addComponent(
lbDatabasePath, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
238 .addComponent(
lbUserPassword, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
241 .addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
242 .addComponent(
lbFullDbPath, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
243 .addGroup(pnSQLiteSettingsLayout.createSequentialGroup()
244 .addComponent(
cbDatabaseType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
245 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
246 .addComponent(
lbSingleUserSqLite, javax.swing.GroupLayout.DEFAULT_SIZE, 467, Short.MAX_VALUE)
248 .addGroup(pnSQLiteSettingsLayout.createSequentialGroup()
250 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
253 .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnSQLiteSettingsLayout.createSequentialGroup()
254 .addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
255 .addComponent(
tbDbHostname, javax.swing.GroupLayout.Alignment.LEADING)
256 .addComponent(
jpDbPassword, javax.swing.GroupLayout.Alignment.LEADING)
258 .addComponent(
tbDbPort, javax.swing.GroupLayout.Alignment.LEADING))
259 .addGap(10, 10, 10))))
260 .addGroup(pnSQLiteSettingsLayout.createSequentialGroup()
262 .addComponent(
filler1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
263 .addGap(0, 0, Short.MAX_VALUE))
265 pnSQLiteSettingsLayout.setVerticalGroup(
266 pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
267 .addGroup(pnSQLiteSettingsLayout.createSequentialGroup()
269 .addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
270 .addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
271 .addComponent(
cbDatabaseType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
273 .addComponent(
lbDatabaseType, javax.swing.GroupLayout.Alignment.TRAILING))
274 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
275 .addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
277 .addComponent(
tfDatabasePath, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
279 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
280 .addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
281 .addComponent(
tbDbHostname, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
283 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
284 .addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
285 .addComponent(
tbDbPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
287 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
288 .addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
289 .addComponent(
tbDbUsername, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
291 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
292 .addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
293 .addComponent(
jpDbPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
295 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
296 .addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
297 .addComponent(
lbFullDbPath, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
298 .addComponent(
lbDatabaseDesc, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
299 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
300 .addComponent(
filler1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
304 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(getContentPane());
305 getContentPane().setLayout(layout);
306 layout.setHorizontalGroup(
307 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
308 .addGroup(layout.createSequentialGroup()
310 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
311 .addComponent(
pnButtons, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
312 .addComponent(
pnSQLiteSettings, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
315 layout.setVerticalGroup(
316 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
317 .addGroup(layout.createSequentialGroup()
319 .addComponent(
pnSQLiteSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
320 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 11, Short.MAX_VALUE)
321 .addComponent(
pnButtons, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
331 switch (selectedPlatform) {
349 this.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
353 @Messages({
"EamDbSettingsDialog.chooserPath.failedToGetDbPathMsg=Selected database path is invalid. Try again."})
356 if (
fcDatabasePath.showOpenDialog(
this) == JFileChooser.APPROVE_OPTION) {
358 if (databaseFile.isFile()) {
364 }
catch (IOException ex) {
365 logger.log(Level.SEVERE,
"Failed to get path of selected database file", ex);
371 switch (selectedPlatform) {
407 @Messages({
"EamDbSettingsDialog.okButton.createDbError.title=Unable to Create Database",
408 "EamDbSettingsDialog.okButton.createSQLiteDbError.message=Unable to create SQLite Database, please ensure location exists and you have write permissions and try again.",
409 "EamDbSettingsDialog.okButton.createPostgresDbError.message=Unable to create Postgres Database, please ensure address, port, and login credentials are correct for Postgres server and try again."})
411 boolean result =
false;
412 boolean dbCreated =
true;
413 switch (selectedPlatform) {
428 JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
429 Bundle.EamDbSettingsDialog_okButton_createPostgresDbError_message(),
430 Bundle.EamDbSettingsDialog_okButton_createDbError_title(),
431 JOptionPane.WARNING_MESSAGE);
432 logger.severe(
"Unable to initialize database schema or insert contents into central repository.");
449 JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
450 Bundle.EamDbSettingsDialog_okButton_createSQLiteDbError_message(),
451 Bundle.EamDbSettingsDialog_okButton_createDbError_title(),
452 JOptionPane.WARNING_MESSAGE);
453 logger.severe(
"Unable to initialize database schema or insert contents into central repository.");
466 boolean wasConfigurationChanged() {
470 @Messages({
"EamDbSettingsDialog.okButton.errorTitle.text=Restart Required.",
471 "EamDbSettingsDialog.okButton.errorMsg.text=Please restart Autopsy to begin using the new database platform.",
472 "EamDbSettingsDialog.okButton.connectionErrorMsg.text=Failed to connect to central repository database.",
473 "EamDbSettingsDialog.okButton.corruptDatabaseExists.title=Error Loading Database",
474 "EamDbSettingsDialog.okButton.corruptDatabaseExists.message=Database exists but is not the right format. Manually delete it or choose a different path (if applicable).",
475 "EamDbSettingsDialog.okButton.createDbDialog.title=Database Does Not Exist",
476 "EamDbSettingsDialog.okButton.createDbDialog.message=Database does not exist, would you like to create it?",
477 "EamDbSettingsDialog.okButton.databaseConnectionFailed.title=Database Connection Failed",
478 "EamDbSettingsDialog.okButton.databaseConnectionFailed.message=Unable to connect to database please check your settings and try again."})
480 setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
483 JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
484 Bundle.EamDbSettingsDialog_okButton_databaseConnectionFailed_message(),
485 Bundle.EamDbSettingsDialog_okButton_databaseConnectionFailed_title(),
486 JOptionPane.WARNING_MESSAGE);
489 JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
490 Bundle.EamDbSettingsDialog_okButton_corruptDatabaseExists_message(),
491 Bundle.EamDbSettingsDialog_okButton_corruptDatabaseExists_title(),
492 JOptionPane.WARNING_MESSAGE);
495 if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(),
496 Bundle.EamDbSettingsDialog_okButton_createDbDialog_message(),
497 Bundle.EamDbSettingsDialog_okButton_createDbDialog_title(),
498 JOptionPane.YES_NO_OPTION)) {
504 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
518 if (null != previousDbManager) {
523 logger.log(Level.SEVERE,
"Failed to close database connections in previously selected platform.", ex);
524 SwingUtilities.invokeLater(() -> {
525 JOptionPane.showMessageDialog(
this,
526 Bundle.EamDbSettingsDialog_okButton_errorMsg_text(),
527 Bundle.EamDbSettingsDialog_okButton_errorTitle_text(),
528 JOptionPane.WARNING_MESSAGE);
538 switch (selectedPlatform) {
546 configurationChanged =
true;
548 logger.log(Level.SEVERE, Bundle.EamDbSettingsDialog_okButton_connectionErrorMsg_text(), ex);
549 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
561 configurationChanged =
true;
563 logger.log(Level.SEVERE, Bundle.EamDbSettingsDialog_okButton_connectionErrorMsg_text(), ex);
564 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
572 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
599 lbPort.setVisible(isPostgres);
610 @Messages({
"EamDbSettingsDialog.textPrompt.hostnameOrIP=Hostname or IP Address",
611 "EamDbSettingsDialog.textPrompt.port=Port Number",
612 "EamDbSettingsDialog.textPrompt.dbName=Database Name",
613 "EamDbSettingsDialog.textPrompt.user=Database User",
614 "EamDbSettingsDialog.textPrompt.password=Database User's Password"})
616 Collection<TextPrompt> textPrompts =
new ArrayList<>();
618 textPrompts.add(
new TextPrompt(Bundle.EamDbSettingsDialog_textPrompt_port(),
tbDbPort));
626 tbDbPort.setText(enabled ? Integer.toString(dbSettingsPostgres.
getPort()) :
"");
668 textPrompt.setForeground(Color.LIGHT_GRAY);
669 textPrompt.changeAlpha(alpha);
680 textFields.forEach((textField) -> {
681 textField.getDocument().addDocumentListener(listener);
691 @Messages({
"EamDbSettingsDialog.validation.incompleteFields=Fill in all values for the selected database."})
693 boolean result =
true;
694 switch (selectedPlatform) {
697 && !
tbDbPort.getText().trim().isEmpty()
731 boolean result =
true;
732 StringBuilder guidanceText =
new StringBuilder();
734 switch (selectedPlatform) {
739 guidanceText.append(ex.getMessage());
744 dbSettingsPostgres.
setPort(Integer.valueOf(
tbDbPort.getText().trim()));
746 guidanceText.append(ex.getMessage());
751 dbSettingsPostgres.
setDbName(CENTRAL_REPO_DB_NAME);
753 guidanceText.append(ex.getMessage());
760 guidanceText.append(ex.getMessage());
767 guidanceText.append(ex.getMessage());
774 dbSettingsSqlite.
setDbName(CENTRAL_REPO_DB_NAME + CENTRAL_REPO_SQLITE_EXT);
777 guidanceText.append(ex.getMessage());
801 @Messages({
"EamDbSettingsDialog.validation.finished=Click OK to save your database settings and return to the Options. Or select a different database type."})
804 bnOk.setEnabled(
true);
806 bnOk.setEnabled(
false);
820 firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
828 firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
836 firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
856 private javax.swing.JButton
bnOk;
DatabaseTestResult testingStatus
boolean createDbDirectory()
javax.swing.JPasswordField jpDbPassword
boolean insertDefaultDatabaseContent()
void setHost(String host)
javax.swing.JLabel lbHostName
void shutdownConnections()
void displayDatabaseSettings(boolean isPostgres)
static final String CENTRAL_REPO_DB_NAME
javax.swing.JTextField tbDbUsername
boolean insertDefaultDatabaseContent()
boolean verifyDatabaseSchema()
javax.swing.JTextField tbDbPort
final PostgresEamDbSettings dbSettingsPostgres
javax.swing.JPanel pnButtons
javax.swing.JButton bnCancel
final SqliteEamDbSettings dbSettingsSqlite
void setTextBoxListeners()
void bnDatabasePathFileOpenActionPerformed(java.awt.event.ActionEvent evt)
static final String CENTRAL_REPO_SQLITE_EXT
boolean verifyConnection()
javax.swing.JComboBox< EamDbPlatformEnum > cbDatabaseType
boolean initializeDatabaseSchema()
javax.swing.JLabel lbPort
static final Logger logger
javax.swing.JLabel lbFullDbPath
javax.swing.ButtonGroup bnGrpDatabasePlatforms
javax.swing.JFileChooser fcDatabasePath
javax.swing.JPanel pnSQLiteSettings
void removeUpdate(DocumentEvent e)
static void addDocumentListeners(Collection< JTextField > textFields, TextBoxChangedListener listener)
void updatePostgresFields(boolean enabled)
void setPassword(String password)
EamDbPlatformEnum selectedPlatform
javax.swing.JButton bnDatabasePathFileOpen
void bnOkActionPerformed(java.awt.event.ActionEvent evt)
void changedUpdate(DocumentEvent e)
boolean databaseSettingsAreValid()
static EamDb getInstance()
void bnCancelActionPerformed(java.awt.event.ActionEvent evt)
javax.swing.JLabel lbDatabaseDesc
javax.swing.Box.Filler filler1
boolean initializeDatabaseSchema()
final Collection< JTextField > textBoxes
boolean verifyDatabaseExists()
static void configureTextPrompts(Collection< TextPrompt > textPrompts)
boolean verifyDatabaseSchema()
void updateSqliteFields(boolean enabled)
void insertUpdate(DocumentEvent e)
javax.swing.JLabel lbUserPassword
boolean databaseFieldsArePopulated()
boolean verifyConnection()
boolean configurationChanged
void setUserName(String userName)
javax.swing.JLabel lbUserName
javax.swing.JLabel lbDatabasePath
void cbDatabaseTypeActionPerformed(java.awt.event.ActionEvent evt)
void setDbName(String dbName)
boolean enableOkButton(boolean isValidInput)
javax.swing.JLabel lbSingleUserSqLite
void setDbName(String dbName)
synchronized static Logger getLogger(String name)
javax.swing.JTextField tbDbHostname
final TextBoxChangedListener textBoxChangedListener
javax.swing.JLabel lbDatabaseType
static final long serialVersionUID
void setDbDirectory(String dbDirectory)
boolean dbDirectoryExists()
javax.swing.JTextField tfDatabasePath
void customizeComponents()