diff --git a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties index 8ba6b8f14e..db8e9e9808 100644 --- a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties @@ -20,8 +20,6 @@ ServicesMonitor.statusChange.notify.title=Service Status Update ServicesMonitor.statusChange.notify.msg=Status for {0} is {1} ServicesMonitor.nullServiceName.excepton.txt=Requested service name is null ServicesMonitor.unknownServiceName.excepton.txt=Requested service name {0} is unknown -TextConverter.convert.exception.txt=Unable to convert text {0} to hex text -TextConverter.convertFromHex.exception.txt=Unable to convert hex text to text ServicesMonitor.KeywordSearchNull=Cannot find Keyword Search service ServicesMonitor.InvalidPortNumber=Invalid port number. ServicesMonitor.remoteCaseDatabase.displayName.text=Multi-user case database service diff --git a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java index 9ca9a4ac02..df63b0fa1f 100755 --- a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java +++ b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java @@ -18,20 +18,16 @@ */ package org.sleuthkit.autopsy.core; -import java.util.Base64; +import org.sleuthkit.autopsy.coreutils.TextConverter; import java.util.prefs.BackingStoreException; import org.sleuthkit.autopsy.events.MessageServiceConnectionInfo; import java.util.prefs.PreferenceChangeListener; import java.util.prefs.Preferences; -import javax.crypto.Cipher; -import javax.crypto.SecretKey; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; -import javax.crypto.spec.PBEParameterSpec; -import org.openide.util.NbBundle; +import org.openide.util.Exceptions; import org.openide.util.NbPreferences; import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.PlatformUtil; +import org.sleuthkit.autopsy.coreutils.TextConverterException; import org.sleuthkit.autopsy.coreutils.Version; import org.sleuthkit.datamodel.CaseDbConnectionInfo; import org.sleuthkit.datamodel.TskData.DbType; @@ -205,12 +201,16 @@ public final class UserPreferences { } catch (Exception ex) { dbType = DbType.SQLITE; } - return new CaseDbConnectionInfo( - preferences.get(EXTERNAL_DATABASE_HOSTNAME_OR_IP, ""), - preferences.get(EXTERNAL_DATABASE_PORTNUMBER, "5432"), - preferences.get(EXTERNAL_DATABASE_USER, ""), - TextConverter.convertHexTextToText(preferences.get(EXTERNAL_DATABASE_PASSWORD, "")), - dbType); + try { + return new CaseDbConnectionInfo( + preferences.get(EXTERNAL_DATABASE_HOSTNAME_OR_IP, ""), + preferences.get(EXTERNAL_DATABASE_PORTNUMBER, "5432"), + preferences.get(EXTERNAL_DATABASE_USER, ""), + TextConverter.convertHexTextToText(preferences.get(EXTERNAL_DATABASE_PASSWORD, "")), + dbType); + } catch (TextConverterException ex) { + throw new UserPreferencesException("Failure converting password hex text to text.", ex); // NON-NLS + } } /** @@ -225,7 +225,11 @@ public final class UserPreferences { preferences.put(EXTERNAL_DATABASE_HOSTNAME_OR_IP, connectionInfo.getHost()); preferences.put(EXTERNAL_DATABASE_PORTNUMBER, connectionInfo.getPort()); preferences.put(EXTERNAL_DATABASE_USER, connectionInfo.getUserName()); - preferences.put(EXTERNAL_DATABASE_PASSWORD, TextConverter.convertTextToHexText(connectionInfo.getPassword())); + try { + preferences.put(EXTERNAL_DATABASE_PASSWORD, TextConverter.convertTextToHexText(connectionInfo.getPassword())); + } catch (TextConverterException ex) { + throw new UserPreferencesException("Failure converting text to password hext text", ex); // NON-NLS + } preferences.put(EXTERNAL_DATABASE_TYPE, connectionInfo.getDbType().toString()); } @@ -267,7 +271,11 @@ public final class UserPreferences { preferences.put(MESSAGE_SERVICE_HOST, info.getHost()); preferences.put(MESSAGE_SERVICE_PORT, Integer.toString(info.getPort())); preferences.put(MESSAGE_SERVICE_USER, info.getUserName()); - preferences.put(MESSAGE_SERVICE_PASSWORD, TextConverter.convertTextToHexText(info.getPassword())); + try { + preferences.put(MESSAGE_SERVICE_PASSWORD, TextConverter.convertTextToHexText(info.getPassword())); + } catch (TextConverterException ex) { + throw new UserPreferencesException("Failed to convert password text to hex text.", ex); + } } /** @@ -286,11 +294,15 @@ public final class UserPreferences { port = DEFAULT_PORT_INT; } - return new MessageServiceConnectionInfo( - preferences.get(MESSAGE_SERVICE_HOST, ""), - port, - preferences.get(MESSAGE_SERVICE_USER, ""), - TextConverter.convertHexTextToText(preferences.get(MESSAGE_SERVICE_PASSWORD, ""))); + try { + return new MessageServiceConnectionInfo( + preferences.get(MESSAGE_SERVICE_HOST, ""), + port, + preferences.get(MESSAGE_SERVICE_USER, ""), + TextConverter.convertHexTextToText(preferences.get(MESSAGE_SERVICE_PASSWORD, ""))); + } catch (TextConverterException ex) { + throw new UserPreferencesException("Failed to convert password hex text to text.", ex); + } } /** @@ -359,66 +371,4 @@ public final class UserPreferences { preferences.put(APP_NAME, name); } - /** - * Provides ability to convert text to hex text. - */ - static final class TextConverter { - - private static final char[] TMP = "hgleri21auty84fwe".toCharArray(); //NON-NLS - private static final byte[] SALT = { - (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12, - (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,}; - - /** - * Convert text to hex text. - * - * @param property Input text string. - * - * @return Converted hex string. - * - * @throws org.sleuthkit.autopsy.core.UserPreferencesException - */ - static String convertTextToHexText(String property) throws UserPreferencesException { - try { - SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES"); //NON-NLS - SecretKey key = keyFactory.generateSecret(new PBEKeySpec(TMP)); - Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES"); //NON-NLS - pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(SALT, 20)); - return base64Encode(pbeCipher.doFinal(property.getBytes("UTF-8"))); - } catch (Exception ex) { - throw new UserPreferencesException( - NbBundle.getMessage(TextConverter.class, "TextConverter.convert.exception.txt")); - } - } - - private static String base64Encode(byte[] bytes) { - return Base64.getEncoder().encodeToString(bytes); - } - - /** - * Convert hex text back to text. - * - * @param property Input hex text string. - * - * @return Converted text string. - * - * @throws org.sleuthkit.autopsy.core.UserPreferencesException - */ - static String convertHexTextToText(String property) throws UserPreferencesException { - try { - SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES"); //NON-NLS - SecretKey key = keyFactory.generateSecret(new PBEKeySpec(TMP)); - Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES"); //NON-NLS - pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(SALT, 20)); - return new String(pbeCipher.doFinal(base64Decode(property)), "UTF-8"); - } catch (Exception ex) { - throw new UserPreferencesException( - NbBundle.getMessage(TextConverter.class, "TextConverter.convertFromHex.exception.txt")); - } - } - - private static byte[] base64Decode(String property) { - return Base64.getDecoder().decode(property); - } - } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.form b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.form index 8957d55bb1..8e379954e9 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.form @@ -45,222 +45,212 @@ - + - + - + - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java index 5b7cf32634..8ad63473d4 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2017 Basis Technology Corp. + * Copyright 2011-2013 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,12 +26,14 @@ import java.awt.event.ActionListener; import java.awt.datatransfer.StringSelection; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Enumeration; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.logging.Level; import javax.swing.JMenuItem; import javax.swing.SwingWorker; import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableColumn; import org.apache.commons.lang.StringUtils; import org.openide.nodes.Node; import org.openide.util.Lookup; @@ -50,7 +52,7 @@ import org.netbeans.swing.etable.ETable; /** * Instances of this class display the BlackboardArtifacts associated with the - * Content represented by a Node. Each BlackboardArtifact is rendered as an HTML + * Content represented by a Node. Each BlackboardArtifact is rendered displayed in a JTable * representation of its BlackboardAttributes. */ @ServiceProvider(service = DataContentViewer.class, position = 3) @@ -75,6 +77,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat Bundle.DataContentViewerArtifact_attrsTableHeader_type(), Bundle.DataContentViewerArtifact_attrsTableHeader_value(), Bundle.DataContentViewerArtifact_attrsTableHeader_sources()}; + private static final int[] COLUMN_WIDTHS = {100, 800, 100}; public DataContentViewerArtifact() { initResultsTable(); @@ -86,30 +89,32 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat private void initResultsTable() { resultsTable = new ETable(); - resultsTable.setModel(new javax.swing.table.DefaultTableModel() { private static final long serialVersionUID = 1L; - @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return false; } - }); resultsTable.setCellSelectionEnabled(true); - resultsTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION); - resultsTable.setColumnHidingAllowed(false); resultsTable.getTableHeader().setReorderingAllowed(false); - resultsTable.setRowSorter(null); //null sorter turns off sorting + resultsTable.setColumnHidingAllowed(false); + resultsTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION); updateColumnSizes(); } private void updateColumnSizes() { resultsTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_NEXT_COLUMN); - if (resultsTable.getColumnModel().getColumnCount() > 0) { - resultsTable.getColumnModel().getColumn(0).setPreferredWidth(100); - resultsTable.getColumnModel().getColumn(1).setPreferredWidth(800); - resultsTable.getColumnModel().getColumn(2).setPreferredWidth(100); + Enumeration columns = resultsTable.getColumnModel().getColumns(); + while (columns.hasMoreElements()) { + TableColumn col = columns.nextElement(); + if (col.getHeaderValue().equals(COLUMN_HEADERS[0])) { + col.setPreferredWidth(COLUMN_WIDTHS[0]); + } else if (col.getHeaderValue().equals(COLUMN_HEADERS[1])) { + col.setPreferredWidth(COLUMN_WIDTHS[1]); + } else if (col.getHeaderValue().equals(COLUMN_HEADERS[2])) { + col.setPreferredWidth(COLUMN_WIDTHS[2]); + } } } @@ -119,13 +124,12 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat * regenerated by the Form Editor. */ @SuppressWarnings("unchecked") - // + // //GEN-BEGIN:initComponents private void initComponents() { rightClickMenu = new javax.swing.JPopupMenu(); copyMenuItem = new javax.swing.JMenuItem(); selectAllMenuItem = new javax.swing.JMenuItem(); - jScrollPane1 = new javax.swing.JScrollPane(); jPanel1 = new javax.swing.JPanel(); totalPageLabel = new javax.swing.JLabel(); ofLabel = new javax.swing.JLabel(); @@ -145,9 +149,6 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat setPreferredSize(new java.awt.Dimension(622, 58)); - jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - jScrollPane1.setPreferredSize(new java.awt.Dimension(622, 58)); - jPanel1.setPreferredSize(new java.awt.Dimension(620, 58)); totalPageLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.totalPageLabel.text")); // NOI18N @@ -197,7 +198,8 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat } }); - resultsTableScrollPane.setPreferredSize(new java.awt.Dimension(620, 271)); + resultsTableScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + resultsTableScrollPane.setPreferredSize(new java.awt.Dimension(620, 34)); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); @@ -218,13 +220,13 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 0, 0) .addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap(366, Short.MAX_VALUE)) .addComponent(resultsTableScrollPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() - .addContainerGap(277, Short.MAX_VALUE) + .addContainerGap(280, Short.MAX_VALUE) .addComponent(artifactLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 258, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(85, Short.MAX_VALUE))) + .addContainerGap(84, Short.MAX_VALUE))) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -239,47 +241,45 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(pageLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(resultsTableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 34, Short.MAX_VALUE)) + .addComponent(resultsTableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 29, Short.MAX_VALUE) + .addGap(0, 0, 0)) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() .addComponent(artifactLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 40, Short.MAX_VALUE))) + .addGap(0, 401, Short.MAX_VALUE))) ); - jScrollPane1.setViewportView(jPanel1); - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 622, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); - }// + }// //GEN-END:initComponents - private void prevPageButtonActionPerformed(java.awt.event.ActionEvent evt) { - currentPage = currentPage - 1; - currentPageLabel.setText(Integer.toString(currentPage)); - artifactLabel.setText(artifactTableContents.get(currentPage - 1).getArtifactDisplayName()); - startNewTask(new SelectedArtifactChangedTask(currentPage)); - } - - private void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt) { + private void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextPageButtonActionPerformed currentPage = currentPage + 1; currentPageLabel.setText(Integer.toString(currentPage)); artifactLabel.setText(artifactTableContents.get(currentPage - 1).getArtifactDisplayName()); startNewTask(new SelectedArtifactChangedTask(currentPage)); - } + }//GEN-LAST:event_nextPageButtonActionPerformed - // Variables declaration - do not modify + private void prevPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_prevPageButtonActionPerformed + currentPage = currentPage - 1; + currentPageLabel.setText(Integer.toString(currentPage)); + artifactLabel.setText(artifactTableContents.get(currentPage - 1).getArtifactDisplayName()); + startNewTask(new SelectedArtifactChangedTask(currentPage)); + }//GEN-LAST:event_prevPageButtonActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel artifactLabel; private javax.swing.JMenuItem copyMenuItem; private javax.swing.JLabel currentPageLabel; private javax.swing.JPanel jPanel1; - private javax.swing.JScrollPane jScrollPane1; private javax.swing.JButton nextPageButton; private javax.swing.JLabel ofLabel; private javax.swing.JLabel pageLabel; @@ -289,7 +289,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat private javax.swing.JPopupMenu rightClickMenu; private javax.swing.JMenuItem selectAllMenuItem; private javax.swing.JLabel totalPageLabel; - // End of variables declaration + // End of variables declaration//GEN-END:variables private ETable resultsTable; private void customizeComponents() { @@ -548,10 +548,6 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat totalPageLabel.setText(Integer.toString(viewUpdate.numberOfPages)); currentPageLabel.setText(Integer.toString(currentPage)); artifactLabel.setText(viewUpdate.tableContents.getArtifactDisplayName()); - // @@@ This can take a long time. Perhaps a faster HTML renderer can be found. - // Note that the rendering appears to be done on a background thread, since the - // wait cursor reset below happens before the new text hits the JTextPane. On the - // other hand, the UI is unresponsive... DefaultTableModel tModel = ((DefaultTableModel) resultsTable.getModel()); tModel.setDataVector(viewUpdate.tableContents.getRows(), COLUMN_HEADERS); updateColumnSizes(); @@ -740,8 +736,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat List artifactContents = getArtifactContents(); ResultsTableArtifact artifactContent = artifactContents.get(pageIndex - 1); - // It may take a considerable amount of time to fetch the attributes of the selected artifact and render them - // as HTML, so check for cancellation. + // It may take a considerable amount of time to fetch the attributes of the selected artifact so check for cancellation. if (isCancelled()) { return null; } diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/Bundle.properties b/Core/src/org/sleuthkit/autopsy/coreutils/Bundle.properties index f633003d1d..e16d1e4fbd 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/coreutils/Bundle.properties @@ -20,4 +20,6 @@ PlatformUtil.getPhysicalMemInfo.usageText=Physical memory usage (max, total, fre PlatformUtil.getAllMemUsageInfo.usageText={0}\n\ {1}\n\ Process Virtual Memory\: {2} -StringExtract.illegalStateException.cannotInit.msg=Unicode table not properly initialized, cannot instantiate StringExtract \ No newline at end of file +StringExtract.illegalStateException.cannotInit.msg=Unicode table not properly initialized, cannot instantiate StringExtract +TextConverter.convert.exception.txt=Unable to convert text {0} to hex text +TextConverter.convertFromHex.exception.txt=Unable to convert hex text to text diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/TextConverter.java b/Core/src/org/sleuthkit/autopsy/coreutils/TextConverter.java new file mode 100644 index 0000000000..b69a411a96 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/coreutils/TextConverter.java @@ -0,0 +1,88 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2017 Basis Technology Corp. + * Contact: carrier sleuthkit 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.coreutils; + +import java.util.Base64; +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.PBEParameterSpec; +import org.openide.util.NbBundle; + +/** + * Provides ability to convert text to hex text. + */ +public final class TextConverter { + + private static final char[] TMP = "hgleri21auty84fwe".toCharArray(); //NON-NLS + private static final byte[] SALT = {(byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12, (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12}; + + /** + * Convert text to hex text. + * + * @param property Input text string. + * + * @return Converted hex string. + * + * @throws org.sleuthkit.autopsy.coreutils.TextConverterException + */ + public static String convertTextToHexText(String property) throws TextConverterException { + try { + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES"); //NON-NLS + SecretKey key = keyFactory.generateSecret(new PBEKeySpec(TMP)); + Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES"); //NON-NLS + pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(SALT, 20)); + return base64Encode(pbeCipher.doFinal(property.getBytes("UTF-8"))); + } catch (Exception ex) { + throw new TextConverterException(NbBundle.getMessage(TextConverter.class, "TextConverter.convert.exception.txt")); + } + } + + public static String base64Encode(byte[] bytes) { + return Base64.getEncoder().encodeToString(bytes); + } + + /** + * Convert hex text back to text. + * + * @param property Input hex text string. + * + * @return Converted text string. + * + * @throws org.sleuthkit.autopsy.coreutils.TextConverterException + */ + public static String convertHexTextToText(String property) throws TextConverterException { + try { + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES"); //NON-NLS + SecretKey key = keyFactory.generateSecret(new PBEKeySpec(TMP)); + Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES"); //NON-NLS + pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(SALT, 20)); + return new String(pbeCipher.doFinal(base64Decode(property)), "UTF-8"); + } catch (Exception ex) { + throw new TextConverterException(NbBundle.getMessage(TextConverter.class, "TextConverter.convertFromHex.exception.txt")); + } + } + + public static byte[] base64Decode(String property) { + return Base64.getDecoder().decode(property); + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/TextConverterException.java b/Core/src/org/sleuthkit/autopsy/coreutils/TextConverterException.java new file mode 100644 index 0000000000..3634d021e2 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/coreutils/TextConverterException.java @@ -0,0 +1,30 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2017 Basis Technology Corp. + * Contact: carrier sleuthkit 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.coreutils; + +/** + * + */ +public class TextConverterException extends Exception { + + public TextConverterException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java index 0d34d62fdd..c25e4c52b0 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * - * Copyright 2011-2016 Basis Technology Corp. + * + * Copyright 2011-2017 Basis Technology Corp. * Contact: carrier sleuthkit 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. @@ -33,6 +33,8 @@ import java.util.Observable; import java.util.Observer; import java.util.Set; import java.util.logging.Level; +import java.util.stream.Collectors; +import org.apache.commons.lang3.StringUtils; import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; @@ -68,18 +70,18 @@ public class KeywordHits implements AutopsyVisitableItem { // String used in the instance MAP so that exact matches and substring can fit into the same // data structure as regexps, even though they don't use instances. private final String DEFAULT_INSTANCE_NAME = "DEFAULT_INSTANCE_NAME"; - + public KeywordHits(SleuthkitCase skCase) { this.skCase = skCase; keywordResults = new KeywordResults(); } - - /* All of these maps and code assume the following: - * Regexps will have an 'instance' layer that shows the specific words that matched the regexp - * Exact match and substring will not have the instance layer and instead will have the specific hits - * below their term. - */ + /* + * All of these maps and code assume the following: Regexps will have an + * 'instance' layer that shows the specific words that matched the regexp + * Exact match and substring will not have the instance layer and instead + * will have the specific hits below their term. + */ private final class KeywordResults extends Observable { // Map from listName/Type to Map of keywords/regexp to Map of instance terms to Set of artifact Ids @@ -104,11 +106,12 @@ public class KeywordHits implements AutopsyVisitableItem { } /** - * Get keywords used in a given list. Will be regexp patterns for regexps - * and search term for non-regexps. - * + * Get keywords used in a given list. Will be regexp patterns for + * regexps and search term for non-regexps. + * * @param listName Keyword list name - * @return + * + * @return */ List getKeywords(String listName) { List keywords; @@ -118,15 +121,16 @@ public class KeywordHits implements AutopsyVisitableItem { Collections.sort(keywords); return keywords; } - + /** - * Get specific keyword terms that were found for a given list - * and keyword combination. For example, a specific phone number for a - * phone number regexp. Will be the default instance for non-regexp searches. - * + * Get specific keyword terms that were found for a given list and + * keyword combination. For example, a specific phone number for a phone + * number regexp. Will be the default instance for non-regexp searches. + * * @param listName Keyword list name - * @param keyword search term (regexp pattern or exact match term) - * @return + * @param keyword search term (regexp pattern or exact match term) + * + * @return */ List getKeywordInstances(String listName, String keyword) { List instances; @@ -139,10 +143,14 @@ public class KeywordHits implements AutopsyVisitableItem { /** * Get artifact ids for a given list, keyword, and instance triple - * @param listName Keyword list name - * @param keyword search term (regexp pattern or exact match term) - * @param keywordInstance specific term that matched (or default instance name) - * @return + * + * @param listName Keyword list name + * @param keyword search term (regexp pattern or exact match + * term) + * @param keywordInstance specific term that matched (or default + * instance name) + * + * @return */ Set getArtifactIds(String listName, String keyword, String keywordInstance) { synchronized (topLevelMap) { @@ -151,11 +159,13 @@ public class KeywordHits implements AutopsyVisitableItem { } /** - * Add a hit for a regexp to the internal data structure. - * @param listMap Maps keywords/regexp to instances to artifact IDs - * @param regExp Regular expression that was used in search + * Add a hit for a regexp to the internal data structure. + * + * @param listMap Maps keywords/regexp to instances to artifact + * IDs + * @param regExp Regular expression that was used in search * @param keywordInstance Specific term that matched regexp - * @param artifactId Artifact id of file that had hit + * @param artifactId Artifact id of file that had hit */ void addRegExpToList(Map>> listMap, String regExp, String keywordInstance, Long artifactId) { if (listMap.containsKey(regExp) == false) { @@ -171,12 +181,13 @@ public class KeywordHits implements AutopsyVisitableItem { // add this ID to the instance instanceMap.get(keywordInstance).add(artifactId); } - - + /** - * Add a hit for a exactmatch (or substring) to the internal data structure. - * @param listMap Maps keywords/regexp to instances to artifact IDs - * @param keyWord Term that was hit + * Add a hit for a exactmatch (or substring) to the internal data + * structure. + * + * @param listMap Maps keywords/regexp to instances to artifact IDs + * @param keyWord Term that was hit * @param artifactId Artifact id of file that had hit */ void addNonRegExpMatchToList(Map>> listMap, String keyWord, Long artifactId) { @@ -191,10 +202,13 @@ public class KeywordHits implements AutopsyVisitableItem { } instanceMap.get(DEFAULT_INSTANCE_NAME).add(artifactId); } - + /** - * Populate data structure for the tree based on the keyword hit artifacts - * @param artifactIds Maps Artifact ID to map of attribute types to attribute values + * Populate data structure for the tree based on the keyword hit + * artifacts + * + * @param artifactIds Maps Artifact ID to map of attribute types to + * attribute values */ void populateTreeMaps(Map> artifactIds) { synchronized (topLevelMap) { @@ -223,7 +237,7 @@ public class KeywordHits implements AutopsyVisitableItem { String reg = attributes.get(Long.valueOf(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID())); // new in 4.4 String kwType = attributes.get(Long.valueOf(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_TYPE.getTypeID())); - + // part of a list if (listName != null) { // get or create list entry @@ -231,7 +245,7 @@ public class KeywordHits implements AutopsyVisitableItem { listsMap.put(listName, new LinkedHashMap<>()); } Map>> listMap = listsMap.get(listName); - + // substring, treated same as exact match // Enum for "1" is defined in KeywordSearch.java if ((kwType != null) && (kwType.equals("1"))) { @@ -241,8 +255,7 @@ public class KeywordHits implements AutopsyVisitableItem { } else { addNonRegExpMatchToList(listMap, word, id); } - } - else if (reg != null) { + } else if (reg != null) { addRegExpToList(listMap, reg, word, id); } else { addNonRegExpMatchToList(listMap, word, id); @@ -259,11 +272,11 @@ public class KeywordHits implements AutopsyVisitableItem { } // literal, single term else { addNonRegExpMatchToList(literalMap, word, id); - } + } } topLevelMap.putAll(listsMap); } - + setChanged(); notifyObservers(); } @@ -299,9 +312,9 @@ public class KeywordHits implements AutopsyVisitableItem { long artifactId = resultSet.getLong("artifact_id"); //NON-NLS long typeId = resultSet.getLong("attribute_type_id"); //NON-NLS if (!artifactIds.containsKey(artifactId)) { - artifactIds.put(artifactId, new LinkedHashMap()); + artifactIds.put(artifactId, new LinkedHashMap<>()); } - if (valueStr != null && !valueStr.equals("")) { + if (StringUtils.isNotEmpty(valueStr)) { artifactIds.get(artifactId).put(typeId, valueStr); } else { // Keyword Search Type is an int @@ -366,7 +379,7 @@ public class KeywordHits implements AutopsyVisitableItem { } /** - * Creates the list nodes + * Creates the list nodes */ private class ListFactory extends ChildFactory.Detachable implements Observer { @@ -458,8 +471,9 @@ public class KeywordHits implements AutopsyVisitableItem { } } - /** - * Represents the keyword search lists (or default groupings if list was not given) + /** + * Represents the keyword search lists (or default groupings if list was not + * given) */ public class ListNode extends DisplayableItemNode implements Observer { @@ -583,17 +597,17 @@ public class KeywordHits implements AutopsyVisitableItem { this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/keyword_hits.png"); //NON-NLS updateDisplayName(); keywordResults.addObserver(this); + } private void updateDisplayName() { - int totalDescendants = 0; - - for (String instance : keywordResults.getKeywordInstances(setName, keyword)) { - Set ids = keywordResults.getArtifactIds(setName, keyword, instance); - totalDescendants += ids.size(); - } - - super.setDisplayName(keyword + " (" + totalDescendants + ")"); + super.setDisplayName(keyword + " (" + countTotalDescendants() + ")"); + } + + private int countTotalDescendants() { + return keywordResults.getKeywordInstances(setName, keyword).stream() + .mapToInt(instance -> keywordResults.getArtifactIds(setName, keyword, instance).size()) + .sum(); } @Override @@ -605,12 +619,7 @@ public class KeywordHits implements AutopsyVisitableItem { public boolean isLeafTypeNode() { List instances = keywordResults.getKeywordInstances(setName, keyword); // is this an exact/substring match (i.e. did we use the DEFAULT name)? - if (instances.size() == 1 && instances.get(0).equals(DEFAULT_INSTANCE_NAME)) { - return true; - } - else { - return false; - } + return instances.size() == 1 && instances.get(0).equals(DEFAULT_INSTANCE_NAME); } @Override @@ -635,7 +644,7 @@ public class KeywordHits implements AutopsyVisitableItem { ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.filesWithHits.name"), NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.filesWithHits.displayName"), NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.filesWithHits.desc"), - keywordResults.getKeywordInstances(setName, keyword).size())); + countTotalDescendants())); return s; } @@ -645,42 +654,50 @@ public class KeywordHits implements AutopsyVisitableItem { return getClass().getName(); } } - + // Allows us to pass in either longs or strings // as they keys for different types of nodes at the // same level. Probably a better way to do this, but // it works. - class RegExpInstanceKey { + private class RegExpInstanceKey { + private final boolean isRegExp; private String strKey; private Long longKey; - public RegExpInstanceKey(String key) { + + RegExpInstanceKey(String key) { isRegExp = true; strKey = key; } - public RegExpInstanceKey(Long key) { + + RegExpInstanceKey(Long key) { isRegExp = false; longKey = key; } + boolean isRegExp() { return isRegExp; } + Long getIdKey() { return longKey; } + String getRegExpKey() { return strKey; } } /** - * Creates the nodes for a given regexp that represent the specific terms that were found + * Creates the nodes for a given regexp that represent the specific terms + * that were found */ public class RegExpInstancesFactory extends ChildFactory.Detachable implements Observer { + private final String keyword; private final String setName; - - private Map nodesMap = new HashMap<>(); + + private final Map nodesMap = new HashMap<>(); public RegExpInstancesFactory(String setName, String keyword) { super(); @@ -700,15 +717,15 @@ public class KeywordHits implements AutopsyVisitableItem { @Override protected boolean createKeys(List list) { - List instances = keywordResults.getKeywordInstances(setName, keyword); + List instances = keywordResults.getKeywordInstances(setName, keyword); // The keys are different depending on what we are displaying. // regexp get another layer to show instances. // Exact/substring matches don't. if ((instances.size() == 1) && (instances.get(0).equals(DEFAULT_INSTANCE_NAME))) { - for (Long id : keywordResults.getArtifactIds(setName, keyword, DEFAULT_INSTANCE_NAME) ) { + for (Long id : keywordResults.getArtifactIds(setName, keyword, DEFAULT_INSTANCE_NAME)) { RegExpInstanceKey key = new RegExpInstanceKey(id); if (!nodesMap.containsKey(key)) { - nodesMap.put(key, createNode(key)); + nodesMap.put(key, createNode(key)); } list.add(key); } @@ -720,7 +737,7 @@ public class KeywordHits implements AutopsyVisitableItem { } list.add(key); } - + } return true; } @@ -731,23 +748,24 @@ public class KeywordHits implements AutopsyVisitableItem { } private DisplayableItemNode createNode(RegExpInstanceKey key) { - // if it isn't a regexp, then skip the 'instance' layer of the tree + // if it isn't a regexp, then skip the 'instance' layer of the tree if (key.isRegExp() == false) { return createBlackboardArtifactNode(key.getIdKey()); } else { return new RegExpInstanceNode(setName, keyword, key.getRegExpKey()); } - + } + @Override public void update(Observable o, Object arg) { refresh(true); } - + } - + /** - * Represents a specific term that was found from a regexp + * Represents a specific term that was found from a regexp */ public class RegExpInstanceNode extends DisplayableItemNode implements Observer { @@ -756,7 +774,7 @@ public class KeywordHits implements AutopsyVisitableItem { private final String instance; public RegExpInstanceNode(String setName, String keyword, String instance) { - super(Children.create(new HitsFactory(setName, keyword, instance), true), Lookups.singleton(keyword)); + super(Children.create(new HitsFactory(setName, keyword, instance), true), Lookups.singleton(instance)); super.setName(instance); //the instance represents the name of the keyword hit at this point as the keyword is the regex this.setName = setName; this.keyword = keyword; @@ -803,7 +821,7 @@ public class KeywordHits implements AutopsyVisitableItem { ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.filesWithHits.name"), NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.filesWithHits.displayName"), NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.filesWithHits.desc"), - keywordResults.getKeywordInstances(setName, keyword).size())); + keywordResults.getArtifactIds(setName, keyword, instance).size())); return s; } @@ -814,12 +832,14 @@ public class KeywordHits implements AutopsyVisitableItem { } } - /** + /** * Create a blackboard node for the given Keyword Hit artifact + * * @param artifactId + * * @return Node or null on error */ - private BlackboardArtifactNode createBlackboardArtifactNode (Long artifactId) { + private BlackboardArtifactNode createBlackboardArtifactNode(Long artifactId) { if (skCase == null) { return null; } @@ -869,7 +889,7 @@ public class KeywordHits implements AutopsyVisitableItem { } return null; } - + /** * Creates nodes for individual files that had hits */ @@ -878,8 +898,8 @@ public class KeywordHits implements AutopsyVisitableItem { private final String keyword; private final String setName; private final String instance; - - private Map nodesMap = new HashMap<>(); + + private final Map nodesMap = new HashMap<>(); public HitsFactory(String setName, String keyword, String instance) { super(); @@ -900,11 +920,11 @@ public class KeywordHits implements AutopsyVisitableItem { @Override protected boolean createKeys(List list) { - for (Long id : keywordResults.getArtifactIds(setName, keyword, instance) ) { + for (Long id : keywordResults.getArtifactIds(setName, keyword, instance)) { if (!nodesMap.containsKey(id)) { - nodesMap.put(id, createBlackboardArtifactNode(id)); + nodesMap.put(id, createBlackboardArtifactNode(id)); } - list.add(id); + list.add(id); } return true; } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/EamCaseEditDetailsDialog.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/EamCaseEditDetailsDialog.java index d2f147419d..d8c24d1a58 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/EamCaseEditDetailsDialog.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/EamCaseEditDetailsDialog.java @@ -524,7 +524,7 @@ public class EamCaseEditDetailsDialog extends JDialog { private void updateDb() { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { LOGGER.log(Level.SEVERE, "Enteprise artifacts manager database not enabled"); // NON-NLS return; } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/EamEditCaseInfoAction.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/EamEditCaseInfoAction.java index 7b7f2db346..7c13f22530 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/EamEditCaseInfoAction.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/EamEditCaseInfoAction.java @@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.actions; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.Action; import org.openide.awt.ActionID; import org.openide.awt.ActionReference; @@ -29,7 +28,7 @@ import org.openide.util.HelpCtx; import org.openide.util.NbBundle.Messages; import org.openide.util.actions.CallableSystemAction; import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.coreutils.ModuleSettings; +import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb; /** * Action to update case details in enterprise artifacts manager database @@ -53,8 +52,7 @@ public final class EamEditCaseInfoAction extends CallableSystemAction implements @Override public boolean isEnabled() { - boolean enabled = Boolean.valueOf(ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.enabled")); // NON-NLS - return enabled && Case.isCaseOpen(); + return EamDb.isEnabled() && Case.isCaseOpen(); } @Override diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/DataContentViewerOtherCases.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/DataContentViewerOtherCases.java index e0ad406386..f4679d52a6 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/DataContentViewerOtherCases.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/DataContentViewerOtherCases.java @@ -504,8 +504,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D @Override public boolean isSupported(Node node) { - EamDb dbManager = EamDb.getInstance(); - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { return false; } @@ -516,8 +515,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D @Override @Messages({"DataContentViewerOtherCases.table.nodbconnection=Cannot connect to enterprise artifacts manager database."}) public void setNode(Node node) { - EamDb dbManager = EamDb.getInstance(); - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { return; } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/AbstractSqlEamDb.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/AbstractSqlEamDb.java index 55145ec8b1..4c7c0e09a4 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/AbstractSqlEamDb.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/AbstractSqlEamDb.java @@ -45,8 +45,7 @@ public abstract class AbstractSqlEamDb implements EamDb { private final static Logger LOGGER = Logger.getLogger(AbstractSqlEamDb.class.getName()); - protected static final int SCHEMA_VERSION = 1; - protected final List DEFAULT_ARTIFACT_TYPES = new ArrayList<>(); + protected final List DEFAULT_ARTIFACT_TYPES; private int bulkArtifactsCount; private int bulkGlobalArtifactsCount; @@ -67,7 +66,7 @@ public abstract class AbstractSqlEamDb implements EamDb { bulkArtifacts = new HashMap<>(); bulkGlobalArtifacts = new HashMap<>(); - loadDefaultArtifactTypes(); + DEFAULT_ARTIFACT_TYPES = EamArtifact.getDefaultArtifactTypes(); for (EamArtifact.Type type : DEFAULT_ARTIFACT_TYPES) { bulkArtifacts.put(type.getName(), new ArrayList<>()); @@ -75,56 +74,6 @@ public abstract class AbstractSqlEamDb implements EamDb { } } - /** - * Load the default correlation artifact types - */ - private void loadDefaultArtifactTypes() { - DEFAULT_ARTIFACT_TYPES.add(new EamArtifact.Type("FILES", true, true)); // NON-NLS - DEFAULT_ARTIFACT_TYPES.add(new EamArtifact.Type("DOMAIN", true, false)); // NON-NLS - DEFAULT_ARTIFACT_TYPES.add(new EamArtifact.Type("EMAIL", true, false)); // NON-NLS - DEFAULT_ARTIFACT_TYPES.add(new EamArtifact.Type("PHONE", true, false)); // NON-NLS - DEFAULT_ARTIFACT_TYPES.add(new EamArtifact.Type("USBID", true, false)); // NON-NLS - } - - /** - * Store the default Correlation Artifact Types in the db. - * - * This should be called immediately following the database schema being - * loaded. - * - * @throws EamDbException - */ - private void storeDefaultArtifactTypes() throws EamDbException { - for (EamArtifact.Type defType : DEFAULT_ARTIFACT_TYPES) { - newCorrelationArtifactType(defType); - } - } - - /** - * Store the schema version into the db_info table. - * - * This should be called immediately following the database schema being - * loaded. - * - * @throws EamDbException - */ - private void storeSchemaVersion() throws EamDbException { - newDbInfo("SCHEMA_VERSION", String.valueOf(SCHEMA_VERSION)); - } - - /** - * Insert all default content into a freshly initialized/reset database. - * - * This should be called immediately following the database schema being - * reset or initialized. - * - * @throws EamDbException - */ - protected void insertDefaultContent() throws EamDbException { - storeDefaultArtifactTypes(); - storeSchemaVersion(); - } - /** * Check to see if the database schema exists and is the current version. - * If it doesn't exist, initialize it and load default content. - If it is @@ -133,86 +82,30 @@ public abstract class AbstractSqlEamDb implements EamDb { * * Note: this should be call after the connectionPool is initialized. */ - protected void confirmDatabaseSchema() throws EamDbException { - int schema_version; - try { - schema_version = Integer.parseInt(getDbInfo("SCHEMA_VERSION")); - } catch (EamDbException | NumberFormatException ex) { - // error likely means we have not initialized the schema - schema_version = 0; - LOGGER.log(Level.WARNING, "Could not find SCHEMA_VERSION in db_info table, assuming database is not initialized.", ex); // NON-NLS - } - - if (0 == schema_version) { - initializeDatabaseSchema(); - insertDefaultContent(); - } else if (SCHEMA_VERSION > schema_version) { - // FUTURE: upgrade schema - } - // else, schema is current - } - - /** - * Create the schema for the selected database implementation - */ - protected abstract void initializeDatabaseSchema() throws EamDbException; +// protected void confirmDatabaseSchema() throws EamDbException { +// int schema_version; +// try { +// schema_version = Integer.parseInt(getDbInfo("SCHEMA_VERSION")); +// } catch (EamDbException | NumberFormatException ex) { +// // error likely means we have not initialized the schema +// schema_version = 0; +// LOGGER.log(Level.WARNING, "Could not find SCHEMA_VERSION in db_info table, assuming database is not initialized.", ex); // NON-NLS +// } +// +// if (0 == schema_version) { +//// initializeDatabaseSchema(); +// insertDefaultContent(); +// } else if (SCHEMA_VERSION > schema_version) { +// // FUTURE: upgrade schema +// } +// // else, schema is current +// } /** * Setup and create a connection to the selected database implementation */ protected abstract Connection connect() throws EamDbException; - /** - * Close the in-use connection and return it to the pool. - * - * @param conn An open connection - * - * @throws EamDbException - */ - protected void closeConnection(Connection conn) throws EamDbException { - if (null != conn) { - try { - conn.close(); - } catch (SQLException ex) { - throw new EamDbException("Error closing Connection.", ex); - } - } - } - - /** - * Close the prepared statement. - * - * @param preparedStatement - * - * @throws EamDbException - */ - protected void closePreparedStatement(PreparedStatement preparedStatement) throws EamDbException { - if (null != preparedStatement) { - try { - preparedStatement.close(); - } catch (SQLException ex) { - throw new EamDbException("Error closing PreparedStatement.", ex); - } - } - } - - /** - * Close the resultSet. - * - * @param resultSet - * - * @throws EamDbException - */ - protected void closeResultSet(ResultSet resultSet) throws EamDbException { - if (null != resultSet) { - try { - resultSet.close(); - } catch (SQLException ex) { - throw new EamDbException("Error closing ResultSet.", ex); - } - } - } - /** * Get the list of tags recognized as "Bad" * @@ -260,8 +153,8 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error adding new name/value pair to db_info.", ex); } finally { - closePreparedStatement(preparedStatement); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeConnection(conn); } } @@ -293,9 +186,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error getting value for name.", ex); } finally { - closePreparedStatement(preparedStatement); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } return value; @@ -323,8 +216,8 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error updating value for name.", ex); } finally { - closePreparedStatement(preparedStatement); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeConnection(conn); } } @@ -366,8 +259,8 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error inserting new case.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeConnection(conn); } } @@ -406,8 +299,8 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error updating case.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeConnection(conn); } } @@ -442,9 +335,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error getting case details.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } return eamCaseResult; @@ -479,9 +372,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error getting all cases.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } return cases; @@ -510,8 +403,8 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error inserting new data source.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeConnection(conn); } } @@ -537,8 +430,8 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error updating case.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeConnection(conn); } } @@ -557,7 +450,7 @@ public abstract class AbstractSqlEamDb implements EamDb { PreparedStatement preparedStatement = null; ResultSet resultSet = null; - String sql = "SELECT * FROM data_sources WHERE device_id=?"; + String sql = "SELECT * FROM data_sources WHERE device_id=?"; // NON-NLS try { preparedStatement = conn.prepareStatement(sql); @@ -569,9 +462,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error getting case details.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } return eamDataSourceResult; @@ -603,9 +496,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error getting all data sources.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } return dataSources; @@ -651,8 +544,8 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error inserting new artifact into artifacts table.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeConnection(conn); } } @@ -697,9 +590,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error getting artifact instances by artifactType and artifactValue.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } return artifactInstances; @@ -749,9 +642,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error getting artifact instances by artifactType and artifactValue.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } return artifactInstances; @@ -790,9 +683,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error getting count of artifact instances by artifactType and artifactValue.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } return instanceCount; @@ -852,9 +745,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error counting unique caseDisplayName/dataSource tuples having artifactType and artifactValue.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } return instanceCount; @@ -897,9 +790,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error counting unique caseDisplayName/dataSource tuples.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } return instanceCount; @@ -953,9 +846,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error counting artifact instances by caseName/dataSource.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } return instanceCount; @@ -1035,8 +928,8 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error inserting bulk artifacts.", ex); // NON-NLS } finally { - closePreparedStatement(bulkPs); - closeConnection(conn); + EamDbUtil.closePreparedStatement(bulkPs); + EamDbUtil.closeConnection(conn); } } @@ -1088,8 +981,8 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error inserting bulk cases.", ex); // NON-NLS } finally { - closePreparedStatement(bulkPs); - closeConnection(conn); + EamDbUtil.closePreparedStatement(bulkPs); + EamDbUtil.closeConnection(conn); } } @@ -1154,10 +1047,10 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error getting/setting artifact instance knownStatus=Bad.", ex); // NON-NLS } finally { - closePreparedStatement(preparedUpdate); - closePreparedStatement(preparedQuery); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedUpdate); + EamDbUtil.closePreparedStatement(preparedQuery); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } } @@ -1202,9 +1095,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error getting known bad artifact instances.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } return artifactInstances; @@ -1241,9 +1134,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error getting count of known bad artifact instances.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } return badInstances; @@ -1292,9 +1185,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error getting known bad artifact instances.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } return caseNames.stream().collect(Collectors.toList()); @@ -1332,9 +1225,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error determining if artifact is globally known bad.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } return 0 < badInstances; @@ -1365,8 +1258,8 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error inserting new organization.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeConnection(conn); } } @@ -1397,9 +1290,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error getting all organizations.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } } @@ -1430,9 +1323,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error getting organization by id.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } } @@ -1477,10 +1370,10 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error inserting new global set.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement1); - closePreparedStatement(preparedStatement2); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement1); + EamDbUtil.closePreparedStatement(preparedStatement2); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } } @@ -1511,9 +1404,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error getting global set by id.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement1); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement1); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } } @@ -1542,8 +1435,8 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error inserting new global file instance into global_files table.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeConnection(conn); } } @@ -1606,8 +1499,8 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error inserting bulk artifacts.", ex); // NON-NLS } finally { - closePreparedStatement(bulkPs); - closeConnection(conn); + EamDbUtil.closePreparedStatement(bulkPs); + EamDbUtil.closeConnection(conn); } } } @@ -1640,9 +1533,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error getting global set by id.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement1); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement1); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } } @@ -1671,8 +1564,8 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error inserting new correlation artifact type.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeConnection(conn); } } @@ -1704,9 +1597,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error getting all correlation artifact types.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } } @@ -1738,9 +1631,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error getting enabled correlation artifact types.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } } @@ -1772,9 +1665,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error getting supported correlation artifact types.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } } @@ -1802,8 +1695,8 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error getting correlation artifact type by name.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeConnection(conn); } } @@ -1836,9 +1729,9 @@ public abstract class AbstractSqlEamDb implements EamDb { } catch (SQLException ex) { throw new EamDbException("Error getting correlation artifact type by name.", ex); // NON-NLS } finally { - closePreparedStatement(preparedStatement); - closeResultSet(resultSet); - closeConnection(conn); + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamArtifact.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamArtifact.java index 090341023c..dd33b5e0e9 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamArtifact.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamArtifact.java @@ -36,6 +36,19 @@ public class EamArtifact implements Serializable { private Type artifactType; private final List artifactInstances; + /** + * Load the default correlation artifact types + */ + public static List getDefaultArtifactTypes() { + List DEFAULT_ARTIFACT_TYPES = new ArrayList<>(); + DEFAULT_ARTIFACT_TYPES.add(new EamArtifact.Type("FILES", true, true)); // NON-NLS + DEFAULT_ARTIFACT_TYPES.add(new EamArtifact.Type("DOMAIN", true, false)); // NON-NLS + DEFAULT_ARTIFACT_TYPES.add(new EamArtifact.Type("EMAIL", true, false)); // NON-NLS + DEFAULT_ARTIFACT_TYPES.add(new EamArtifact.Type("PHONE", true, false)); // NON-NLS + DEFAULT_ARTIFACT_TYPES.add(new EamArtifact.Type("USBID", true, false)); // NON-NLS + return DEFAULT_ARTIFACT_TYPES; + } + public EamArtifact(Type artifactType, String artifactValue) { this.ID = ""; this.artifactType = artifactType; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDb.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDb.java index a5b71de42a..0f7a1839cc 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDb.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDb.java @@ -24,11 +24,12 @@ import java.util.List; * Main interface for interacting with the database */ public interface EamDb { + public static final int SCHEMA_VERSION = 1; /** - * Get the instance; default to SQLITE. + * Get the instance * - * @return The EamDb instance + * @return The EamDb instance or null if one is not configured. * * @throws EamDbException */ @@ -40,8 +41,9 @@ public interface EamDb { return PostgresEamDb.getInstance(); case SQLITE: - default: return SqliteEamDb.getInstance(); + default: + return null; } } @@ -65,7 +67,9 @@ public interface EamDb { * * @return Is the database enabled */ - boolean isEnabled(); + static boolean isEnabled() { + return EamDbPlatformEnum.getSelectedPlatform() != EamDbPlatformEnum.DISABLED; + } /** * Get the list of tags recognized as "Bad" diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDbPlatformEnum.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDbPlatformEnum.java index bc02377430..2b117d326d 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDbPlatformEnum.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDbPlatformEnum.java @@ -24,7 +24,8 @@ import org.sleuthkit.autopsy.coreutils.ModuleSettings; * */ public enum EamDbPlatformEnum { - SQLITE("SQLite", true), + DISABLED("Disabled", true), + SQLITE("SQLite", false), POSTGRESQL("PostgreSQL", false); private final String platformName; @@ -44,6 +45,8 @@ public enum EamDbPlatformEnum { if (null != selectedPlatformString) { selected = this.toString().equalsIgnoreCase(selectedPlatformString); + } else if (this == DISABLED) { + selected = true; } } @@ -56,13 +59,13 @@ public enum EamDbPlatformEnum { this.selected = selected; } - private Boolean isSelected() { + public Boolean isSelected() { return selected; } public static EamDbPlatformEnum fromString(String pName) { if (null == pName) { - return SQLITE; + return DISABLED; } for (EamDbPlatformEnum p : EamDbPlatformEnum.values()) { @@ -70,14 +73,14 @@ public enum EamDbPlatformEnum { return p; } } - return SQLITE; + return DISABLED; } /** * Save the selected platform to the config file. */ public static void saveSelectedPlatform() { - EamDbPlatformEnum selectedPlatform = SQLITE; + EamDbPlatformEnum selectedPlatform = DISABLED; for (EamDbPlatformEnum p : EamDbPlatformEnum.values()) { if (p.isSelected()) { selectedPlatform = p; @@ -103,7 +106,7 @@ public enum EamDbPlatformEnum { * Get the selected platform. * * @return The selected platform, or if not platform is selected, default to - * SQLITE. + * DISABLED. */ public static EamDbPlatformEnum getSelectedPlatform() { for (EamDbPlatformEnum p : EamDbPlatformEnum.values()) { @@ -111,6 +114,6 @@ public enum EamDbPlatformEnum { return p; } } - return SQLITE; + return DISABLED; } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDbUtil.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDbUtil.java new file mode 100644 index 0000000000..3d5dbe3d5c --- /dev/null +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDbUtil.java @@ -0,0 +1,184 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; +import java.util.logging.Level; +import org.sleuthkit.autopsy.coreutils.Logger; +import static org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb.SCHEMA_VERSION; + +/** + * + */ +public class EamDbUtil { + private final static Logger LOGGER = Logger.getLogger(EamDbUtil.class.getName()); + + /** + * Close the prepared statement. + * + * @param preparedStatement + * + * @throws EamDbException + */ + public static void closePreparedStatement(PreparedStatement preparedStatement) { + if (null != preparedStatement) { + try { + preparedStatement.close(); + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, "Error closing PreparedStatement.", ex); + } + } + } + + /** + * Close the resultSet. + * + * @param resultSet + * + * @throws EamDbException + */ + public static void closeResultSet(ResultSet resultSet) { + if (null != resultSet) { + try { + resultSet.close(); + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, "Error closing ResultSet.", ex); + } + } + } + + /** + * Close the in-use connection and return it to the pool. + * + * @param conn An open connection + * + * @throws EamDbException + */ + public static void closeConnection(Connection conn) { + if (null != conn) { + try { + conn.close(); + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, "Error closing Connection.", ex); + } + } + } + + /** + * Insert the default artifact types into the database. + * + * @param conn Open connection to use. + * @return true on success, else false + */ + public static boolean insertDefaultArtifactTypes(Connection conn) { + PreparedStatement preparedStatement = null; + List DEFAULT_ARTIFACT_TYPES = EamArtifact.getDefaultArtifactTypes(); + String sql = "INSERT INTO artifact_types(name, supported, enabled) VALUES (?, ?, ?)"; + + try { + preparedStatement = conn.prepareStatement(sql); + for (EamArtifact.Type newType : DEFAULT_ARTIFACT_TYPES) { + preparedStatement.setString(1, newType.getName()); + preparedStatement.setInt(2, newType.isSupported() ? 1 : 0); + preparedStatement.setInt(3, newType.isEnabled() ? 1 : 0); + preparedStatement.addBatch(); + } + preparedStatement.executeBatch(); + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, "Error inserting default correlation artifact types.", ex); // NON-NLS + return false; + } finally { + EamDbUtil.closePreparedStatement(preparedStatement); + } + return true; + } + + /** + * Store the schema version into the db_info table. + * + * This should be called immediately following the database schema being + * loaded. + * + * @param conn Open connection to use. + * @return true on success, else false + */ + public static boolean insertSchemaVersion(Connection conn) { + PreparedStatement preparedStatement = null; + String sql = "INSERT INTO db_info (name, value) VALUES (?, ?)"; + try { + preparedStatement = conn.prepareStatement(sql); + preparedStatement.setString(1, "SCHEMA_VERSION"); + preparedStatement.setString(2, String.valueOf(SCHEMA_VERSION)); + preparedStatement.executeUpdate(); + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, "Error adding schema version to db_info.", ex); + return false; + } finally { + EamDbUtil.closePreparedStatement(preparedStatement); + } + return true; + } + + /** + * Query to see if the SCHEMA_VERSION is set in the db. + * + * @return true if set, else false. + */ + public static boolean schemaVersionIsSet(Connection conn) { + if (null == conn) { + return false; + } + + ResultSet resultSet = null; + try { + Statement tester = conn.createStatement(); + String sql = "SELECT value FROM db_info WHERE name='SCHEMA_VERSION'"; + resultSet = tester.executeQuery(sql); + if (resultSet.next()) { + String value = resultSet.getString("value"); + } + } catch (SQLException ex) { + return false; + } finally { + EamDbUtil.closeResultSet(resultSet); + } + return true; + } + + /** + * Use the current settings and the validation query + * to test the connection to the database. + * + * @return true if successfull query execution, else false. + */ + public static boolean executeValidationQuery(Connection conn, String validationQuery) { + if (null == conn) { + return false; + } + + ResultSet resultSet = null; + try { + Statement tester = conn.createStatement(); + resultSet = tester.executeQuery(validationQuery); + if (resultSet.next()) { + return true; + } + } catch (SQLException ex) { + return false; + } finally { + EamDbUtil.closeResultSet(resultSet); + } + + return false; + } +} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDb.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDb.java index 52f60b1950..0815d9997b 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDb.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDb.java @@ -90,10 +90,10 @@ public class PostgresEamDb extends AbstractSqlEamDb { } catch (SQLException ex) { //LOGGER.log(Level.WARNING, "Failed to reset database.", ex); } finally { - closeConnection(conn); + EamDbUtil.closeConnection(conn); } - insertDefaultContent(); + dbSettings.insertDefaultDatabaseContent(); } /** @@ -113,12 +113,10 @@ public class PostgresEamDb extends AbstractSqlEamDb { connectionURL.append(dbSettings.getPort()); connectionURL.append("/"); connectionURL.append(dbSettings.getDbName()); - connectionURL.append("?user="); - connectionURL.append(dbSettings.getUserName()); - connectionURL.append("&password="); - connectionURL.append(dbSettings.getPassword()); - + connectionPool.setUrl(connectionURL.toString()); + connectionPool.setUsername(dbSettings.getUserName()); + connectionPool.setPassword(dbSettings.getPassword()); // tweak pool configuration connectionPool.setInitialSize(5); // start with 5 connections @@ -126,175 +124,6 @@ public class PostgresEamDb extends AbstractSqlEamDb { connectionPool.setValidationQuery(dbSettings.getValidationQuery()); } - /** - * Initialize the database schema. - * - * Requires valid connectionPool. - * - * This method is called from within connect(), so we cannot call connect() - * to get a connection. This method is called after setupConnectionPool(), - * so it is safe to assume that a valid connectionPool exists. The - * implementation of connect() is synchronized, so we can safely use the - * connectionPool object directly. - */ - @Override - protected void initializeDatabaseSchema() throws EamDbException { - // The "id" column is an alias for the built-in 64-bit int "rowid" column. - // It is autoincrementing by default and must be of type "integer primary key". - // We've omitted the autoincrement argument because we are not currently - // using the id value to search for specific rows, so we do not care - // if a rowid is re-used after an existing rows was previously deleted. - StringBuilder createOrganizationsTable = new StringBuilder(); - createOrganizationsTable.append("CREATE TABLE IF NOT EXISTS organizations ("); - createOrganizationsTable.append("id SERIAL PRIMARY KEY,"); - createOrganizationsTable.append("org_name text NOT NULL,"); - createOrganizationsTable.append("poc_name text NOT NULL,"); - createOrganizationsTable.append("poc_email text NOT NULL,"); - createOrganizationsTable.append("poc_phone text NOT NULL"); - createOrganizationsTable.append(")"); - - // NOTE: The organizations will only have a small number of rows, so - // an index is probably not worthwhile. - - StringBuilder createCasesTable = new StringBuilder(); - createCasesTable.append("CREATE TABLE IF NOT EXISTS cases ("); - createCasesTable.append("id SERIAL PRIMARY KEY,"); - createCasesTable.append("case_uid text NOT NULL,"); - createCasesTable.append("org_id integer,"); - createCasesTable.append("case_name text NOT NULL,"); - createCasesTable.append("creation_date text NOT NULL,"); - createCasesTable.append("case_number text NOT NULL,"); - createCasesTable.append("examiner_name text NOT NULL,"); - createCasesTable.append("examiner_email text NOT NULL,"); - createCasesTable.append("examiner_phone text NOT NULL,"); - createCasesTable.append("notes text NOT NULL,"); - createCasesTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null"); - createCasesTable.append(")"); - - // NOTE: when there are few cases in the cases table, these indices may not be worthwhile - String casesIdx1 = "CREATE INDEX IF NOT EXISTS cases_org_id ON cases (org_id)"; - String casesIdx2 = "CREATE INDEX IF NOT EXISTS cases_case_uid ON cases (case_uid)"; - - StringBuilder createDataSourcesTable = new StringBuilder(); - createDataSourcesTable.append("CREATE TABLE IF NOT EXISTS data_sources ("); - createDataSourcesTable.append("id SERIAL PRIMARY KEY,"); - createDataSourcesTable.append("device_id text NOT NULL,"); - createDataSourcesTable.append("name text NOT NULL,"); - createDataSourcesTable.append("CONSTRAINT device_id_unique UNIQUE (device_id)"); - createDataSourcesTable.append(")"); - - String dataSourceIdx1 = "CREATE INDEX IF NOT EXISTS data_sources_name ON data_sources (name)"; - - StringBuilder createGlobalReferenceSetsTable = new StringBuilder(); - createGlobalReferenceSetsTable.append("CREATE TABLE IF NOT EXISTS global_reference_sets ("); - createGlobalReferenceSetsTable.append("id SERIAL PRIMARY KEY,"); - createGlobalReferenceSetsTable.append("org_id integer,"); - createGlobalReferenceSetsTable.append("set_name text NOT NULL,"); - createGlobalReferenceSetsTable.append("version text NOT NULL,"); - createGlobalReferenceSetsTable.append("import_date text NOT NULL,"); - createGlobalReferenceSetsTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null"); - createGlobalReferenceSetsTable.append(")"); - - String globalReferenceSetsIdx1 = "CREATE INDEX IF NOT EXISTS global_reference_sets_org_id ON global_reference_sets (org_id)"; - - StringBuilder createGlobalFilesTable = new StringBuilder(); - createGlobalFilesTable.append("CREATE TABLE IF NOT EXISTS global_files ("); - createGlobalFilesTable.append("id SERIAL PRIMARY KEY,"); - createGlobalFilesTable.append("global_reference_set_id integer,"); - createGlobalFilesTable.append("value text NOT NULL,"); - createGlobalFilesTable.append("known_status text NOT NULL,"); - createGlobalFilesTable.append("comment text NOT NULL,"); - createGlobalFilesTable.append("CONSTRAINT global_files_multi_unique UNIQUE (global_reference_set_id,value),"); - createGlobalFilesTable.append("foreign key (global_reference_set_id) references global_reference_sets(id) on update set null on delete set null"); - createGlobalFilesTable.append(")"); - - String globalFilesIdx1 = "CREATE INDEX IF NOT EXISTS global_files_value ON global_files (value)"; - String globalFilesIdx2 = "CREATE INDEX IF NOT EXISTS global_files_value_known_status ON global_files (value, known_status)"; - - StringBuilder createArtifactTypesTable = new StringBuilder(); - createArtifactTypesTable.append("CREATE TABLE IF NOT EXISTS artifact_types ("); - createArtifactTypesTable.append("id SERIAL PRIMARY KEY,"); - createArtifactTypesTable.append("name text NOT NULL,"); - createArtifactTypesTable.append("supported integer NOT NULL,"); - createArtifactTypesTable.append("enabled integer NOT NULL,"); - createArtifactTypesTable.append("CONSTRAINT artifact_type_name_unique UNIQUE (name)"); - createArtifactTypesTable.append(")"); - - // NOTE: there are API methods that query by one of: name, supported, or enabled. - // Only name is currently implemented, but, there will only be a small number - // of artifact_types, so there is no benefit to having any indices. - StringBuilder createArtifactInstancesTableTemplate = new StringBuilder(); - createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s_instances ("); - createArtifactInstancesTableTemplate.append("id SERIAL PRIMARY KEY,"); - createArtifactInstancesTableTemplate.append("case_id integer,"); - createArtifactInstancesTableTemplate.append("data_source_id integer,"); - createArtifactInstancesTableTemplate.append("value text NOT NULL,"); - createArtifactInstancesTableTemplate.append("file_path text NOT NULL,"); - createArtifactInstancesTableTemplate.append("known_status text NOT NULL,"); - createArtifactInstancesTableTemplate.append("comment text NOT NULL,"); - createArtifactInstancesTableTemplate.append("CONSTRAINT %s_instances_multi_unique_ UNIQUE (case_id, data_source_id, value, file_path),"); - createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) on update set null on delete set null,"); - createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) on update set null on delete set null"); - createArtifactInstancesTableTemplate.append(")"); - - // TODO: do we need any more indices? - String instancesIdx1 = "CREATE INDEX IF NOT EXISTS %s_instances_case_id ON %s_instances (case_id)"; - String instancesIdx2 = "CREATE INDEX IF NOT EXISTS %s_instances_data_source_id ON %s_instances (data_source_id)"; - String instancesIdx3 = "CREATE INDEX IF NOT EXISTS %s_instances_value ON %s_instances (value)"; - String instancesIdx4 = "CREATE INDEX IF NOT EXISTS %s_instances_value_known_status ON %s_instances (value, known_status)"; - - StringBuilder createDbInfoTable = new StringBuilder(); - createDbInfoTable.append("CREATE TABLE IF NOT EXISTS db_info ("); - createDbInfoTable.append("id SERIAL PRIMARY KEY NOT NULL,"); - createDbInfoTable.append("name text NOT NULL,"); - createDbInfoTable.append("value text NOT NULL"); - createDbInfoTable.append(")"); - - // NOTE: the db_info table currenly only has 1 row, so having an index - // provides no benefit. - - Connection conn = null; - try { - conn = connectionPool.getConnection(); - Statement stmt = conn.createStatement(); - - stmt.execute(createOrganizationsTable.toString()); - - stmt.execute(createCasesTable.toString()); - stmt.execute(casesIdx1); - stmt.execute(casesIdx2); - - stmt.execute(createDataSourcesTable.toString()); - stmt.execute(dataSourceIdx1); - - stmt.execute(createGlobalReferenceSetsTable.toString()); - stmt.execute(globalReferenceSetsIdx1); - - stmt.execute(createGlobalFilesTable.toString()); - stmt.execute(globalFilesIdx1); - stmt.execute(globalFilesIdx2); - - stmt.execute(createArtifactTypesTable.toString()); - - stmt.execute(createDbInfoTable.toString()); - - // Create a separate table for each artifact type - String type_name; - for (EamArtifact.Type type : DEFAULT_ARTIFACT_TYPES) { - type_name = type.getName(); - stmt.execute(String.format(createArtifactInstancesTableTemplate.toString(), type_name, type_name)); - stmt.execute(String.format(instancesIdx1, type_name, type_name)); - stmt.execute(String.format(instancesIdx2, type_name, type_name)); - stmt.execute(String.format(instancesIdx3, type_name, type_name)); - stmt.execute(String.format(instancesIdx4, type_name, type_name)); - } - } catch (SQLException ex) { - throw new EamDbException("Error initializing db schema.", ex); // NON-NLS - } finally { - closeConnection(conn); - } - } - /** * Lazily setup Singleton connection on first request. * @@ -305,13 +134,12 @@ public class PostgresEamDb extends AbstractSqlEamDb { @Override protected Connection connect() throws EamDbException { synchronized (this) { - if (!dbSettings.isEnabled()) { + if (!EamDb.isEnabled()) { throw new EamDbException("Enterprise artifacts manager is not enabled"); // NON-NLS } if (connectionPool == null) { setupConnectionPool(); - confirmDatabaseSchema(); } } @@ -322,11 +150,6 @@ public class PostgresEamDb extends AbstractSqlEamDb { } } - @Override - public boolean isEnabled() { - return dbSettings.isEnabled(); - } - @Override public List getBadTags() { return dbSettings.getBadTags(); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDbSettings.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDbSettings.java index 7b08740354..58d99981a6 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDbSettings.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDbSettings.java @@ -20,15 +20,20 @@ package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; import java.sql.Connection; import java.sql.DriverManager; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Properties; import java.util.logging.Level; +import java.util.regex.Pattern; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ModuleSettings; +import org.sleuthkit.autopsy.coreutils.TextConverter; +import org.sleuthkit.autopsy.coreutils.TextConverterException; /** * Settings for the Postgres implementation of the enterprise artifacts manager @@ -39,7 +44,7 @@ public final class PostgresEamDbSettings { private final static Logger LOGGER = Logger.getLogger(PostgresEamDbSettings.class.getName()); private final String DEFAULT_HOST = "localhost"; // NON-NLS private final int DEFAULT_PORT = 5432; - private final String DEFAULT_DBNAME = "enterpriseartifactmanagerdb"; // NON-NLS + private final String DEFAULT_DBNAME = "enterpriseartifacts"; // NON-NLS private final int DEFAULT_BULK_THRESHHOLD = 1000; private final String DEFAULT_USERNAME = ""; private final String DEFAULT_PASSWORD = ""; @@ -47,8 +52,8 @@ public final class PostgresEamDbSettings { private final String VALIDATION_QUERY = "SELECT version()"; // NON-NLS private final String JDBC_BASE_URI = "jdbc:postgresql://"; // NON-NLS private final String JDBC_DRIVER = "org.postgresql.Driver"; // NON-NLS - - private boolean enabled; + private final String DB_NAMES_REGEX = "[a-z][a-z0-9_]*"; // only lower case + private final String DB_USER_NAMES_REGEX = "[a-zA-Z]\\w*"; private String host; private int port; private String dbName; @@ -62,8 +67,6 @@ public final class PostgresEamDbSettings { } public void loadSettings() { - enabled = Boolean.valueOf(ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.enabled")); // NON-NLS - host = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.host"); // NON-NLS if (host == null || host.isEmpty()) { host = DEFAULT_HOST; @@ -110,6 +113,13 @@ public final class PostgresEamDbSettings { password = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.password"); // NON-NLS if (password == null || password.isEmpty()) { password = DEFAULT_PASSWORD; + } else { + try { + password = TextConverter.convertHexTextToText(password); + } catch (TextConverterException ex) { + LOGGER.log(Level.WARNING, "Failed to convert password from hex text to text.", ex); + password = DEFAULT_PASSWORD; + } } String badTagsStr = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.badTags"); // NON-NLS @@ -120,69 +130,338 @@ public final class PostgresEamDbSettings { } public void saveSettings() { - ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.enabled", Boolean.toString(isEnabled())); // NON-NLS ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.host", getHost()); // NON-NLS ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.port", Integer.toString(port)); // NON-NLS ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.dbName", getDbName()); // NON-NLS ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.bulkThreshold", Integer.toString(getBulkThreshold())); // NON-NLS ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.user", getUserName()); // NON-NLS - ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.password", getPassword()); // NON-NLS + try { + ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.password", TextConverter.convertTextToHexText(getPassword())); // NON-NLS + } catch (TextConverterException ex) { + LOGGER.log(Level.SEVERE, "Failed to convert password from text to hex text.", ex); + } + ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.badTags", String.join(",", badTags)); // NON-NLS } /** * Get the full connection URL as a String * + * @param usePostgresDb Connect to the 'postgres' database when testing + * connectivity and creating the main database. + * * @return */ - public String getConnectionURL() { + public String getConnectionURL(boolean usePostgresDb) { StringBuilder url = new StringBuilder(); url.append(getJDBCBaseURI()); url.append(getHost()); url.append("/"); // NON-NLS - url.append(getDbName()); - url.append("?user="); // NON-NLS - url.append(getUserName()); - url.append("&password="); // NON-NLS - url.append(getPassword()); + if (usePostgresDb) { + url.append("postgres"); // NON-NLS + } else { + url.append(getDbName()); + } return url.toString(); } - public boolean testSettings() { - // Open a new ephemeral client here to test that we can connect - ResultSet resultSet = null; - Connection conn = null; + /** + * Use the current settings to get an ephemeral client connection for testing. + * + * @return Connection or null. + */ + private Connection getEphemeralConnection(boolean usePostgresDb) { + Connection conn; try { - String url = getConnectionURL(); + String url = getConnectionURL(usePostgresDb); + Properties props = new Properties(); + props.setProperty("user", getUserName()); + props.setProperty("password", getPassword()); + Class.forName(getDriver()); - conn = DriverManager.getConnection(url); - Statement tester = conn.createStatement(); - resultSet = tester.executeQuery(getValidationQuery()); - if (resultSet.next()) { - LOGGER.log(Level.INFO, "Testing connection to postgresql success."); // NON-NLS - } + conn = DriverManager.getConnection(url, props); } catch (ClassNotFoundException | SQLException ex) { - LOGGER.log(Level.INFO, "Testing connection to postgresql failed.", ex); // NON-NLS + // TODO: Determine why a connection failure (ConnectionException) re-throws + // the SQLException and does not print this log message? + LOGGER.log(Level.SEVERE, "Failed to acquire ephemeral connection to postgresql."); // NON-NLS + conn = null; + } + return conn; + } + + /** + * Use the current settings and the validation query + * to test the connection to the database. + * + * @return true if successfull connection, else false. + */ + public boolean verifyConnection() { + Connection conn = getEphemeralConnection(true); + if (null == conn) { + return false; + } + + boolean result = EamDbUtil.executeValidationQuery(conn, VALIDATION_QUERY); + EamDbUtil.closeConnection(conn); + return result; + } + + /** + * Check to see if the database exists. + * + * @return true if exists, else false + */ + public boolean verifyDatabaseExists() { + Connection conn = getEphemeralConnection(true); + if (null == conn) { return false; - } finally { - if (null != resultSet) { - try { - resultSet.close(); - } catch (SQLException ex) { - LOGGER.log(Level.SEVERE, "Error closing ResultSet.", ex); // NON-NLS - } - } - if (null != conn) { - try { - conn.close(); - } catch (SQLException ex) { - LOGGER.log(Level.SEVERE, "Error closing test connection.", ex); // NON-NLS - } - } } + String sql = "SELECT datname FROM pg_catalog.pg_database WHERE lower(datname) = lower(?) LIMIT 1"; // NON-NLS + PreparedStatement ps = null; + ResultSet rs = null; + try { + ps = conn.prepareStatement(sql); + ps.setString(1, getDbName()); + rs = ps.executeQuery(); + if (rs.next()) { + return true; + } + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, "Failed to execute database existance query.", ex); // NON-NLS + return false; + } finally { + EamDbUtil.closePreparedStatement(ps); + EamDbUtil.closeResultSet(rs); + EamDbUtil.closeConnection(conn); + } + return false; + } + + /** + * Use the current settings and the schema version query + * to test the database schema. + * + * @return true if successfull connection, else false. + */ + public boolean verifyDatabaseSchema() { + Connection conn = getEphemeralConnection(false); + if (null == conn) { + return false; + } + + boolean result = EamDbUtil.schemaVersionIsSet(conn); + + EamDbUtil.closeConnection(conn); + return result; + } + + public boolean createDatabase() { + Connection conn = getEphemeralConnection(true); + if (null == conn) { + return false; + } + + String sql = "CREATE DATABASE %s OWNER %s"; // NON-NLS + try { + Statement stmt; + stmt = conn.createStatement(); + stmt.execute(String.format(sql, getDbName(), getUserName())); + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, "Failed to execute create database statement.", ex); // NON-NLS + return false; + } finally { + EamDbUtil.closeConnection(conn); + } return true; + + } + /** + * Initialize the database schema. + * + * Requires valid connectionPool. + * + * This method is called from within connect(), so we cannot call connect() + * to get a connection. This method is called after setupConnectionPool(), + * so it is safe to assume that a valid connectionPool exists. The + * implementation of connect() is synchronized, so we can safely use the + * connectionPool object directly. + */ + public boolean initializeDatabaseSchema() { + // The "id" column is an alias for the built-in 64-bit int "rowid" column. + // It is autoincrementing by default and must be of type "integer primary key". + // We've omitted the autoincrement argument because we are not currently + // using the id value to search for specific rows, so we do not care + // if a rowid is re-used after an existing rows was previously deleted. + StringBuilder createOrganizationsTable = new StringBuilder(); + createOrganizationsTable.append("CREATE TABLE IF NOT EXISTS organizations ("); + createOrganizationsTable.append("id SERIAL PRIMARY KEY,"); + createOrganizationsTable.append("org_name text NOT NULL,"); + createOrganizationsTable.append("poc_name text NOT NULL,"); + createOrganizationsTable.append("poc_email text NOT NULL,"); + createOrganizationsTable.append("poc_phone text NOT NULL"); + createOrganizationsTable.append(")"); + + // NOTE: The organizations will only have a small number of rows, so + // an index is probably not worthwhile. + + StringBuilder createCasesTable = new StringBuilder(); + createCasesTable.append("CREATE TABLE IF NOT EXISTS cases ("); + createCasesTable.append("id SERIAL PRIMARY KEY,"); + createCasesTable.append("case_uid text NOT NULL,"); + createCasesTable.append("org_id integer,"); + createCasesTable.append("case_name text NOT NULL,"); + createCasesTable.append("creation_date text NOT NULL,"); + createCasesTable.append("case_number text NOT NULL,"); + createCasesTable.append("examiner_name text NOT NULL,"); + createCasesTable.append("examiner_email text NOT NULL,"); + createCasesTable.append("examiner_phone text NOT NULL,"); + createCasesTable.append("notes text NOT NULL,"); + createCasesTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null"); + createCasesTable.append(")"); + + // NOTE: when there are few cases in the cases table, these indices may not be worthwhile + String casesIdx1 = "CREATE INDEX IF NOT EXISTS cases_org_id ON cases (org_id)"; + String casesIdx2 = "CREATE INDEX IF NOT EXISTS cases_case_uid ON cases (case_uid)"; + + StringBuilder createDataSourcesTable = new StringBuilder(); + createDataSourcesTable.append("CREATE TABLE IF NOT EXISTS data_sources ("); + createDataSourcesTable.append("id SERIAL PRIMARY KEY,"); + createDataSourcesTable.append("device_id text NOT NULL,"); + createDataSourcesTable.append("name text NOT NULL,"); + createDataSourcesTable.append("CONSTRAINT device_id_unique UNIQUE (device_id)"); + createDataSourcesTable.append(")"); + + String dataSourceIdx1 = "CREATE INDEX IF NOT EXISTS data_sources_name ON data_sources (name)"; + + StringBuilder createGlobalReferenceSetsTable = new StringBuilder(); + createGlobalReferenceSetsTable.append("CREATE TABLE IF NOT EXISTS global_reference_sets ("); + createGlobalReferenceSetsTable.append("id SERIAL PRIMARY KEY,"); + createGlobalReferenceSetsTable.append("org_id integer,"); + createGlobalReferenceSetsTable.append("set_name text NOT NULL,"); + createGlobalReferenceSetsTable.append("version text NOT NULL,"); + createGlobalReferenceSetsTable.append("import_date text NOT NULL,"); + createGlobalReferenceSetsTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null"); + createGlobalReferenceSetsTable.append(")"); + + String globalReferenceSetsIdx1 = "CREATE INDEX IF NOT EXISTS global_reference_sets_org_id ON global_reference_sets (org_id)"; + + StringBuilder createGlobalFilesTable = new StringBuilder(); + createGlobalFilesTable.append("CREATE TABLE IF NOT EXISTS global_files ("); + createGlobalFilesTable.append("id SERIAL PRIMARY KEY,"); + createGlobalFilesTable.append("global_reference_set_id integer,"); + createGlobalFilesTable.append("value text NOT NULL,"); + createGlobalFilesTable.append("known_status text NOT NULL,"); + createGlobalFilesTable.append("comment text NOT NULL,"); + createGlobalFilesTable.append("CONSTRAINT global_files_multi_unique UNIQUE (global_reference_set_id,value),"); + createGlobalFilesTable.append("foreign key (global_reference_set_id) references global_reference_sets(id) on update set null on delete set null"); + createGlobalFilesTable.append(")"); + + String globalFilesIdx1 = "CREATE INDEX IF NOT EXISTS global_files_value ON global_files (value)"; + String globalFilesIdx2 = "CREATE INDEX IF NOT EXISTS global_files_value_known_status ON global_files (value, known_status)"; + + StringBuilder createArtifactTypesTable = new StringBuilder(); + createArtifactTypesTable.append("CREATE TABLE IF NOT EXISTS artifact_types ("); + createArtifactTypesTable.append("id SERIAL PRIMARY KEY,"); + createArtifactTypesTable.append("name text NOT NULL,"); + createArtifactTypesTable.append("supported integer NOT NULL,"); + createArtifactTypesTable.append("enabled integer NOT NULL,"); + createArtifactTypesTable.append("CONSTRAINT artifact_type_name_unique UNIQUE (name)"); + createArtifactTypesTable.append(")"); + + // NOTE: there are API methods that query by one of: name, supported, or enabled. + // Only name is currently implemented, but, there will only be a small number + // of artifact_types, so there is no benefit to having any indices. + StringBuilder createArtifactInstancesTableTemplate = new StringBuilder(); + createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s_instances ("); + createArtifactInstancesTableTemplate.append("id SERIAL PRIMARY KEY,"); + createArtifactInstancesTableTemplate.append("case_id integer,"); + createArtifactInstancesTableTemplate.append("data_source_id integer,"); + createArtifactInstancesTableTemplate.append("value text NOT NULL,"); + createArtifactInstancesTableTemplate.append("file_path text NOT NULL,"); + createArtifactInstancesTableTemplate.append("known_status text NOT NULL,"); + createArtifactInstancesTableTemplate.append("comment text NOT NULL,"); + createArtifactInstancesTableTemplate.append("CONSTRAINT %s_instances_multi_unique_ UNIQUE (case_id, data_source_id, value, file_path),"); + createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) on update set null on delete set null,"); + createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) on update set null on delete set null"); + createArtifactInstancesTableTemplate.append(")"); + + // TODO: do we need any more indices? + String instancesIdx1 = "CREATE INDEX IF NOT EXISTS %s_instances_case_id ON %s_instances (case_id)"; + String instancesIdx2 = "CREATE INDEX IF NOT EXISTS %s_instances_data_source_id ON %s_instances (data_source_id)"; + String instancesIdx3 = "CREATE INDEX IF NOT EXISTS %s_instances_value ON %s_instances (value)"; + String instancesIdx4 = "CREATE INDEX IF NOT EXISTS %s_instances_value_known_status ON %s_instances (value, known_status)"; + + StringBuilder createDbInfoTable = new StringBuilder(); + createDbInfoTable.append("CREATE TABLE IF NOT EXISTS db_info ("); + createDbInfoTable.append("id SERIAL PRIMARY KEY NOT NULL,"); + createDbInfoTable.append("name text NOT NULL,"); + createDbInfoTable.append("value text NOT NULL"); + createDbInfoTable.append(")"); + + // NOTE: the db_info table currenly only has 1 row, so having an index + // provides no benefit. + + Connection conn = null; + try { + conn = getEphemeralConnection(false); + if (null == conn) { + return false; + } + Statement stmt = conn.createStatement(); + + stmt.execute(createOrganizationsTable.toString()); + + stmt.execute(createCasesTable.toString()); + stmt.execute(casesIdx1); + stmt.execute(casesIdx2); + + stmt.execute(createDataSourcesTable.toString()); + stmt.execute(dataSourceIdx1); + + stmt.execute(createGlobalReferenceSetsTable.toString()); + stmt.execute(globalReferenceSetsIdx1); + + stmt.execute(createGlobalFilesTable.toString()); + stmt.execute(globalFilesIdx1); + stmt.execute(globalFilesIdx2); + + stmt.execute(createArtifactTypesTable.toString()); + + stmt.execute(createDbInfoTable.toString()); + + // Create a separate table for each artifact type + List DEFAULT_ARTIFACT_TYPES = EamArtifact.getDefaultArtifactTypes(); + String type_name; + for (EamArtifact.Type type : DEFAULT_ARTIFACT_TYPES) { + type_name = type.getName(); + stmt.execute(String.format(createArtifactInstancesTableTemplate.toString(), type_name, type_name)); + stmt.execute(String.format(instancesIdx1, type_name, type_name)); + stmt.execute(String.format(instancesIdx2, type_name, type_name)); + stmt.execute(String.format(instancesIdx3, type_name, type_name)); + stmt.execute(String.format(instancesIdx4, type_name, type_name)); + } + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, "Error initializing db schema.", ex); // NON-NLS + return false; + } finally { + EamDbUtil.closeConnection(conn); + } + return true; + } + + public boolean insertDefaultDatabaseContent() { + Connection conn = getEphemeralConnection(false); + if (null == conn) { + return false; + } + + boolean result = EamDbUtil.insertDefaultArtifactTypes(conn) + && EamDbUtil.insertSchemaVersion(conn); + EamDbUtil.closeConnection(conn); + + return result; } public boolean isChanged() { @@ -198,20 +477,6 @@ public final class PostgresEamDbSettings { || !userName.equals(userNameString) || !password.equals(userPasswordString); } - /** - * @return the enabled - */ - public boolean isEnabled() { - return enabled; - } - - /** - * @param enabled the enabled to set - */ - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - /** * @return the host */ @@ -226,7 +491,7 @@ public final class PostgresEamDbSettings { if (null != host && !host.isEmpty()) { this.host = host; } else { - throw new EamDbException("Error invalid host for database connection. Cannot be null or empty."); // NON-NLS + throw new EamDbException("Invalid host name. Cannot be empty."); // NON-NLS } } @@ -244,27 +509,31 @@ public final class PostgresEamDbSettings { if (port > 0 && port < 65535) { this.port = port; } else { - throw new EamDbException("Error invalid port for database connection."); // NON-NLS + throw new EamDbException("Invalid port. Must be a number greater than 0."); // NON-NLS } } /** + * To prevent issues where one command can honor case and another cannot, + * we will force the dbname to lower case. + * * @return the dbName */ public String getDbName() { - return dbName; + return dbName.toLowerCase(); } /** * @param dbName the dbName to set */ public void setDbName(String dbName) throws EamDbException { - if (dbName != null && !dbName.isEmpty()) { - this.dbName = dbName; - } else { - throw new EamDbException("Error invalid name for database connection. Cannot be null or empty."); // NON-NLS - + if (dbName == null || dbName.isEmpty()) { + throw new EamDbException("Invalid database name. Cannot be empty."); // NON-NLS + } else if (!Pattern.matches(DB_NAMES_REGEX, dbName)) { + throw new EamDbException("Invalid database name. Name must start with a letter and can only contain letters, numbers, and '_'."); // NON-NLS } + + this.dbName = dbName.toLowerCase(); } /** @@ -281,7 +550,7 @@ public final class PostgresEamDbSettings { if (bulkThreshold > 0) { this.bulkThreshold = bulkThreshold; } else { - throw new EamDbException("Error invalid bulk threshold for database connection."); // NON-NLS + throw new EamDbException("Invalid bulk threshold for database connection."); // NON-NLS } } @@ -296,11 +565,12 @@ public final class PostgresEamDbSettings { * @param userName the userName to set */ public void setUserName(String userName) throws EamDbException { - if (userName != null && !userName.isEmpty()) { - this.userName = userName; - } else { - throw new EamDbException("Error invalid user name for database connection. Cannot be null or empty."); // NON-NLS + if (userName == null || userName.isEmpty()) { + throw new EamDbException("Invalid user name. Cannot be empty."); // NON-NLS + } else if (!Pattern.matches(DB_USER_NAMES_REGEX, userName)) { + throw new EamDbException("Invalid user name. Name must start with a letter and can only contain letters, numbers, and '_'."); // NON-NLS } + this.userName = userName; } /** @@ -314,11 +584,10 @@ public final class PostgresEamDbSettings { * @param password the password to set */ public void setPassword(String password) throws EamDbException { - if (password != null && !password.isEmpty()) { - this.password = password; - } else { - throw new EamDbException("Error invalid user password for database connection. Cannot be null or empty."); // NON-NLS + if (password == null || password.isEmpty()) { + throw new EamDbException("Invalid user password. Cannot be empty."); // NON-NLS } + this.password = password; } /** diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDb.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDb.java index 3e43ca97c1..e720955308 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDb.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDb.java @@ -19,8 +19,6 @@ package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; import java.io.File; -import java.io.IOException; -import java.nio.file.Files; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; @@ -38,13 +36,6 @@ public class SqliteEamDb extends AbstractSqlEamDb { private static SqliteEamDb instance; - protected static final String PRAGMA_SYNC_OFF = "PRAGMA synchronous = OFF"; - protected static final String PRAGMA_SYNC_NORMAL = "PRAGMA synchronous = NORMAL"; - private static final String PRAGMA_JOURNAL_WAL = "PRAGMA journal_mode = WAL"; - private static final String PRAGMA_READ_UNCOMMITTED_TRUE = "PRAGMA read_uncommitted = True"; - private static final String PRAGMA_ENCODING_UTF8 = "PRAGMA encoding = 'UTF-8'"; - private static final String PRAGMA_PAGE_SIZE_4096 = "PRAGMA page_size = 4096"; - private static final String PRAGMA_FOREIGN_KEYS_ON = "PRAGMA foreign_keys = ON"; private BasicDataSource connectionPool = null; private final SqliteEamDbSettings dbSettings; @@ -97,12 +88,12 @@ public class SqliteEamDb extends AbstractSqlEamDb { } dropContent.executeUpdate("VACUUM"); - insertDefaultContent(); + dbSettings.insertDefaultDatabaseContent(); } catch (SQLException ex) { LOGGER.log(Level.WARNING, "Failed to reset database.", ex); } finally { - closeConnection(conn); + EamDbUtil.closeConnection(conn); } } @@ -130,202 +121,6 @@ public class SqliteEamDb extends AbstractSqlEamDb { connectionPool.setValidationQuery(dbSettings.getValidationQuery()); } - /** - * Verify the EAM db directory exists. If it doesn't, then create it. - * - * @throws EamDbException - */ - private void verifyDBDirectory() throws EamDbException { - File dbDir = new File(dbSettings.getDbDirectory()); - if (!dbDir.exists()) { - LOGGER.log(Level.INFO, "sqlite directory does not exist, creating it at {0}.", dbSettings.getDbDirectory()); // NON-NLS - try { - Files.createDirectories(dbDir.toPath()); - } catch (IOException ex) { - throw new EamDbException("Failed to create sqlite database directory. ", ex); // NON-NLS - } - } else if (dbDir.exists() && !dbDir.isDirectory()) { - LOGGER.log(Level.INFO, "Failed to create sqlite database directory. Path already exists and is not a directory: {0}", dbSettings.getDbDirectory()); // NON-NLS - } - - } - - /** - * Initialize the database schema. - * - * Requires valid connectionPool. - * - * This method is called from within connect(), so we cannot call connect() - * to get a connection. This method is called after setupConnectionPool(), - * so it is safe to assume that a valid connectionPool exists. The - * implementation of connect() is synchronized, so we can safely use the - * connectionPool object directly. - */ - @Override - protected void initializeDatabaseSchema() throws EamDbException { - // The "id" column is an alias for the built-in 64-bit int "rowid" column. - // It is autoincrementing by default and must be of type "integer primary key". - // We've omitted the autoincrement argument because we are not currently - // using the id value to search for specific rows, so we do not care - // if a rowid is re-used after an existing rows was previously deleted. - StringBuilder createOrganizationsTable = new StringBuilder(); - createOrganizationsTable.append("CREATE TABLE IF NOT EXISTS organizations ("); - createOrganizationsTable.append("id integer primary key autoincrement NOT NULL,"); - createOrganizationsTable.append("org_name text NOT NULL,"); - createOrganizationsTable.append("poc_name text NOT NULL,"); - createOrganizationsTable.append("poc_email text NOT NULL,"); - createOrganizationsTable.append("poc_phone text NOT NULL"); - createOrganizationsTable.append(")"); - - // NOTE: The organizations will only have a small number of rows, so - // an index is probably not worthwhile. - - StringBuilder createCasesTable = new StringBuilder(); - createCasesTable.append("CREATE TABLE IF NOT EXISTS cases ("); - createCasesTable.append("id integer primary key autoincrement NOT NULL,"); - createCasesTable.append("case_uid text NOT NULL,"); - createCasesTable.append("org_id integer,"); - createCasesTable.append("case_name text NOT NULL,"); - createCasesTable.append("creation_date text NOT NULL,"); - createCasesTable.append("case_number text NOT NULL,"); - createCasesTable.append("examiner_name text NOT NULL,"); - createCasesTable.append("examiner_email text NOT NULL,"); - createCasesTable.append("examiner_phone text NOT NULL,"); - createCasesTable.append("notes text NOT NULL,"); - createCasesTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null,"); - createCasesTable.append("CONSTRAINT case_uid_unique UNIQUE(case_uid)"); - createCasesTable.append(")"); - - // NOTE: when there are few cases in the cases table, these indices may not be worthwhile - String casesIdx1 = "CREATE INDEX IF NOT EXISTS cases_org_id ON cases (org_id)"; - String casesIdx2 = "CREATE INDEX IF NOT EXISTS cases_case_uid ON cases (case_uid)"; - - StringBuilder createDataSourcesTable = new StringBuilder(); - createDataSourcesTable.append("CREATE TABLE IF NOT EXISTS data_sources ("); - createDataSourcesTable.append("id integer primary key autoincrement NOT NULL,"); - createDataSourcesTable.append("device_id text NOT NULL,"); - createDataSourcesTable.append("name text NOT NULL,"); - createDataSourcesTable.append("CONSTRAINT device_id_unique UNIQUE(device_id)"); - createDataSourcesTable.append(")"); - - String dataSourceIdx1 = "CREATE INDEX IF NOT EXISTS data_sources_name ON data_sources (name)"; - - StringBuilder createGlobalReferenceSetsTable = new StringBuilder(); - createGlobalReferenceSetsTable.append("CREATE TABLE IF NOT EXISTS global_reference_sets ("); - createGlobalReferenceSetsTable.append("id integer primary key autoincrement NOT NULL,"); - createGlobalReferenceSetsTable.append("org_id integer,"); - createGlobalReferenceSetsTable.append("set_name text NOT NULL,"); - createGlobalReferenceSetsTable.append("version text NOT NULL,"); - createGlobalReferenceSetsTable.append("import_date text NOT NULL,"); - createGlobalReferenceSetsTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null"); - createGlobalReferenceSetsTable.append(")"); - - String globalReferenceSetsIdx1 = "CREATE INDEX IF NOT EXISTS global_reference_sets_org_id ON global_reference_sets (org_id)"; - - StringBuilder createGlobalFilesTable = new StringBuilder(); - createGlobalFilesTable.append("CREATE TABLE IF NOT EXISTS global_files ("); - createGlobalFilesTable.append("id integer primary key autoincrement NOT NULL,"); - createGlobalFilesTable.append("global_reference_set_id integer,"); - createGlobalFilesTable.append("value text NOT NULL,"); - createGlobalFilesTable.append("known_status text NOT NULL,"); - createGlobalFilesTable.append("comment text NOT NULL,"); - createGlobalFilesTable.append("CONSTRAINT global_files_multi_unique UNIQUE(global_reference_set_id, value)"); - createGlobalFilesTable.append("foreign key (global_reference_set_id) references global_reference_sets(id) on update set null on delete set null"); - createGlobalFilesTable.append(")"); - - String globalFilesIdx1 = "CREATE INDEX IF NOT EXISTS global_files_value ON global_files (value)"; - String globalFilesIdx2 = "CREATE INDEX IF NOT EXISTS global_files_value_known_status ON global_files (value, known_status)"; - - StringBuilder createArtifactTypesTable = new StringBuilder(); - createArtifactTypesTable.append("CREATE TABLE IF NOT EXISTS artifact_types ("); - createArtifactTypesTable.append("id integer primary key autoincrement NOT NULL,"); - createArtifactTypesTable.append("name text NOT NULL,"); - createArtifactTypesTable.append("supported integer NOT NULL,"); - createArtifactTypesTable.append("enabled integer NOT NULL,"); - createArtifactTypesTable.append("CONSTRAINT artifact_type_name_unique UNIQUE (name)"); - createArtifactTypesTable.append(")"); - - // NOTE: there are API methods that query by one of: name, supported, or enabled. - // Only name is currently implemented, but, there will only be a small number - // of artifact_types, so there is no benefit to having any indices. - StringBuilder createArtifactInstancesTableTemplate = new StringBuilder(); - createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s_instances ("); - createArtifactInstancesTableTemplate.append("id integer primary key autoincrement NOT NULL,"); - createArtifactInstancesTableTemplate.append("case_id integer,"); - createArtifactInstancesTableTemplate.append("data_source_id integer,"); - createArtifactInstancesTableTemplate.append("value text NOT NULL,"); - createArtifactInstancesTableTemplate.append("file_path text NOT NULL,"); - createArtifactInstancesTableTemplate.append("known_status text NOT NULL,"); - createArtifactInstancesTableTemplate.append("comment text NOT NULL,"); - createArtifactInstancesTableTemplate.append("CONSTRAINT %s_instances_multi_unique UNIQUE(case_id, data_source_id, value, file_path),"); - createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) on update set null on delete set null,"); - createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) on update set null on delete set null"); - createArtifactInstancesTableTemplate.append(")"); - - // TODO: do we need any more indices? - String instancesIdx1 = "CREATE INDEX IF NOT EXISTS %s_instances_case_id ON %s_instances (case_id)"; - String instancesIdx2 = "CREATE INDEX IF NOT EXISTS %s_instances_data_source_id ON %s_instances (data_source_id)"; - String instancesIdx3 = "CREATE INDEX IF NOT EXISTS %s_instances_value ON %s_instances (value)"; - String instancesIdx4 = "CREATE INDEX IF NOT EXISTS %s_instances_value_known_status ON %s_instances (value, known_status)"; - - StringBuilder createDbInfoTable = new StringBuilder(); - createDbInfoTable.append("CREATE TABLE IF NOT EXISTS db_info ("); - createDbInfoTable.append("id integer primary key NOT NULL,"); - createDbInfoTable.append("name text NOT NULL,"); - createDbInfoTable.append("value text NOT NULL"); - createDbInfoTable.append(")"); - - // NOTE: the db_info table currenly only has 1 row, so having an index - // provides no benefit. - - Connection conn = null; - try { - conn = connectionPool.getConnection(); - Statement stmt = conn.createStatement(); - stmt.execute(PRAGMA_JOURNAL_WAL); - stmt.execute(PRAGMA_SYNC_OFF); - stmt.execute(PRAGMA_READ_UNCOMMITTED_TRUE); - stmt.execute(PRAGMA_ENCODING_UTF8); - stmt.execute(PRAGMA_PAGE_SIZE_4096); - stmt.execute(PRAGMA_FOREIGN_KEYS_ON); - - stmt.execute(createOrganizationsTable.toString()); - - stmt.execute(createCasesTable.toString()); - stmt.execute(casesIdx1); - stmt.execute(casesIdx2); - - stmt.execute(createDataSourcesTable.toString()); - stmt.execute(dataSourceIdx1); - - stmt.execute(createGlobalReferenceSetsTable.toString()); - stmt.execute(globalReferenceSetsIdx1); - - stmt.execute(createGlobalFilesTable.toString()); - stmt.execute(globalFilesIdx1); - stmt.execute(globalFilesIdx2); - - stmt.execute(createArtifactTypesTable.toString()); - - stmt.execute(createDbInfoTable.toString()); - - // Create a separate table for each artifact type - String type_name; - for (EamArtifact.Type type : DEFAULT_ARTIFACT_TYPES) { - type_name = type.getName(); - stmt.execute(String.format(createArtifactInstancesTableTemplate.toString(), type_name, type_name)); - stmt.execute(String.format(instancesIdx1, type_name, type_name)); - stmt.execute(String.format(instancesIdx2, type_name, type_name)); - stmt.execute(String.format(instancesIdx3, type_name, type_name)); - stmt.execute(String.format(instancesIdx4, type_name, type_name)); - } - } catch (SQLException ex) { - throw new EamDbException("Error initializing db schema.", ex); // NON-NLS - } finally { - closeConnection(conn); - } - } - /** * Lazily setup Singleton connection on first request. * @@ -336,14 +131,12 @@ public class SqliteEamDb extends AbstractSqlEamDb { @Override protected Connection connect() throws EamDbException { synchronized (this) { - if (!dbSettings.isEnabled()) { + if (!EamDb.isEnabled()) { throw new EamDbException("Enterprise artifacts manager is not enabled"); // NON-NLS } if (connectionPool == null) { - verifyDBDirectory(); setupConnectionPool(); - confirmDatabaseSchema(); } try { @@ -354,11 +147,6 @@ public class SqliteEamDb extends AbstractSqlEamDb { } } - @Override - public boolean isEnabled() { - return dbSettings.isEnabled(); - } - @Override public List getBadTags() { return dbSettings.getBadTags(); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDbSettings.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDbSettings.java index ede8e04d51..742863ab33 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDbSettings.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDbSettings.java @@ -23,13 +23,13 @@ import java.io.IOException; import java.nio.file.Files; import java.sql.Connection; import java.sql.DriverManager; -import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.logging.Level; +import java.util.regex.Pattern; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.PlatformUtil; @@ -41,14 +41,20 @@ public final class SqliteEamDbSettings { private final static Logger LOGGER = Logger.getLogger(SqliteEamDbSettings.class.getName()); private final String DEFAULT_DBNAME = "EnterpriseArtifacts.db"; // NON-NLS - private final String DEFAULT_DBDIRECTORY = PlatformUtil.getUserDirectory() + File.separator + "Autopsy" + File.separator + "eamdb"; // NON-NLS + private final String DEFAULT_DBDIRECTORY = PlatformUtil.getUserDirectory() + File.separator + "enterprise_artifacts_manager"; // NON-NLS private final int DEFAULT_BULK_THRESHHOLD = 1000; private final String DEFAULT_BAD_TAGS = "Evidence"; // NON-NLS private final String JDBC_DRIVER = "org.sqlite.JDBC"; // NON-NLS private final String JDBC_BASE_URI = "jdbc:sqlite:"; // NON-NLS private final String VALIDATION_QUERY = "SELECT count(*) from sqlite_master"; // NON-NLS - - private boolean enabled; + private static final String PRAGMA_SYNC_OFF = "PRAGMA synchronous = OFF"; + private static final String PRAGMA_SYNC_NORMAL = "PRAGMA synchronous = NORMAL"; + private static final String PRAGMA_JOURNAL_WAL = "PRAGMA journal_mode = WAL"; + private static final String PRAGMA_READ_UNCOMMITTED_TRUE = "PRAGMA read_uncommitted = True"; + private static final String PRAGMA_ENCODING_UTF8 = "PRAGMA encoding = 'UTF-8'"; + private static final String PRAGMA_PAGE_SIZE_4096 = "PRAGMA page_size = 4096"; + private static final String PRAGMA_FOREIGN_KEYS_ON = "PRAGMA foreign_keys = ON"; + private final String DB_NAMES_REGEX = "[a-zA-Z]\\w*(\\.db)?"; private String dbName; private String dbDirectory; private int bulkThreshold; @@ -59,8 +65,6 @@ public final class SqliteEamDbSettings { } public void loadSettings() { - enabled = Boolean.valueOf(ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.enabled")); // NON-NLS - dbName = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.sqlite.dbName"); // NON-NLS if (dbName == null || dbName.isEmpty()) { dbName = DEFAULT_DBNAME; @@ -93,29 +97,48 @@ public final class SqliteEamDbSettings { } public void saveSettings() { - createAndVerifyDirectory(); + createDbDirectory(); - ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.enabled", Boolean.toString(isEnabled())); // NON-NLS ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.sqlite.dbName", getDbName()); // NON-NLS ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.sqlite.dbDirectory", getDbDirectory()); // NON-NLS ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.sqlite.bulkThreshold", Integer.toString(getBulkThreshold())); // NON-NLS ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.badTags", String.join(",", badTags)); // NON-NLS } - public boolean createAndVerifyDirectory() { + /** + * Verify that the db directory path exists. + * + * @return true if exists, else false + */ + public boolean dbDirectoryExists() { // Ensure dbDirectory is a valid directory File dbDir = new File(getDbDirectory()); + if (!dbDir.exists()) { - LOGGER.log(Level.INFO, "sqlite directory does not exist, creating it at {0}.", getDbDirectory()); // NON-NLS + return false; + } else if (!dbDir.isDirectory()) { + return false; + } + + return true; + + } + + /** + * Create the db directory if it does not exist. + * + * @return true is successfully created or already exists, else false + */ + public boolean createDbDirectory() { + if (!dbDirectoryExists()) { try { + File dbDir = new File(getDbDirectory()); Files.createDirectories(dbDir.toPath()); + LOGGER.log(Level.INFO, "sqlite directory did not exist, created it at {0}.", getDbDirectory()); // NON-NLS } catch (IOException ex) { - LOGGER.log(Level.INFO, "Failed to create sqlite database directory.", ex); // NON-NLS + LOGGER.log(Level.SEVERE, "Failed to create sqlite database directory.", ex); // NON-NLS return false; } - } else if (dbDir.exists() && !dbDir.isDirectory()) { - LOGGER.log(Level.INFO, "Failed to create sqlite database directory. Path already exists and is not a directory."); // NON-NLS - return false; } return true; @@ -134,46 +157,258 @@ public final class SqliteEamDbSettings { return url.toString(); } - public boolean testSettings() { - if (!createAndVerifyDirectory()) { - return false; + /** + * Use the current settings to get an ephemeral client connection for testing. + * + * If the directory path does not exist, it will return null. + * + * @return Connection or null. + */ + private Connection getEphemeralConnection() { + if (!dbDirectoryExists()) { + return null; } - // Open a new ephemeral client here to test that we can connect - ResultSet resultSet = null; - Connection conn = null; + Connection conn; try { String url = getConnectionURL(); Class.forName(getDriver()); conn = DriverManager.getConnection(url); - Statement tester = conn.createStatement(); - resultSet = tester.executeQuery(getValidationQuery()); - if (resultSet.next()) { - LOGGER.log(Level.INFO, "Testing connection to sqlite success."); // NON-NLS - } } catch (ClassNotFoundException | SQLException ex) { - LOGGER.log(Level.INFO, "Testing connection to sqlite failed.", ex); // NON-NLS + LOGGER.log(Level.SEVERE, "Failed to acquire ephemeral connection to sqlite.", ex); // NON-NLS + conn = null; + } + return conn; + } + + /** + * Use the current settings and the validation query + * to test the connection to the database. + * + * @return true if successfull connection, else false. + */ + public boolean verifyConnection() { + Connection conn = getEphemeralConnection(); + if (null == conn) { + return false; + } + + boolean result = EamDbUtil.executeValidationQuery(conn, VALIDATION_QUERY); + EamDbUtil.closeConnection(conn); + return result; + } + + /** + * Use the current settings and the schema version query + * to test the database schema. + * + * @return true if successfull connection, else false. + */ + public boolean verifyDatabaseSchema() { + Connection conn = getEphemeralConnection(); + if (null == conn) { return false; - } finally { - if (null != resultSet) { - try { - resultSet.close(); - } catch (SQLException ex) { - LOGGER.log(Level.SEVERE, "Error closing ResultSet.", ex); // NON-NLS - } - } - if (null != conn) { - try { - conn.close(); - } catch (SQLException ex) { - LOGGER.log(Level.SEVERE, "Error closing test connection.", ex); // NON-NLS - } - } } + boolean result = EamDbUtil.schemaVersionIsSet(conn); + EamDbUtil.closeConnection(conn); + return result; + } + + /** + * Initialize the database schema. + * + * Requires valid connectionPool. + * + * This method is called from within connect(), so we cannot call connect() + * to get a connection. This method is called after setupConnectionPool(), + * so it is safe to assume that a valid connectionPool exists. The + * implementation of connect() is synchronized, so we can safely use the + * connectionPool object directly. + */ + public boolean initializeDatabaseSchema() { + // The "id" column is an alias for the built-in 64-bit int "rowid" column. + // It is autoincrementing by default and must be of type "integer primary key". + // We've omitted the autoincrement argument because we are not currently + // using the id value to search for specific rows, so we do not care + // if a rowid is re-used after an existing rows was previously deleted. + StringBuilder createOrganizationsTable = new StringBuilder(); + createOrganizationsTable.append("CREATE TABLE IF NOT EXISTS organizations ("); + createOrganizationsTable.append("id integer primary key autoincrement NOT NULL,"); + createOrganizationsTable.append("org_name text NOT NULL,"); + createOrganizationsTable.append("poc_name text NOT NULL,"); + createOrganizationsTable.append("poc_email text NOT NULL,"); + createOrganizationsTable.append("poc_phone text NOT NULL"); + createOrganizationsTable.append(")"); + + // NOTE: The organizations will only have a small number of rows, so + // an index is probably not worthwhile. + + StringBuilder createCasesTable = new StringBuilder(); + createCasesTable.append("CREATE TABLE IF NOT EXISTS cases ("); + createCasesTable.append("id integer primary key autoincrement NOT NULL,"); + createCasesTable.append("case_uid text NOT NULL,"); + createCasesTable.append("org_id integer,"); + createCasesTable.append("case_name text NOT NULL,"); + createCasesTable.append("creation_date text NOT NULL,"); + createCasesTable.append("case_number text NOT NULL,"); + createCasesTable.append("examiner_name text NOT NULL,"); + createCasesTable.append("examiner_email text NOT NULL,"); + createCasesTable.append("examiner_phone text NOT NULL,"); + createCasesTable.append("notes text NOT NULL,"); + createCasesTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null,"); + createCasesTable.append("CONSTRAINT case_uid_unique UNIQUE(case_uid)"); + createCasesTable.append(")"); + + // NOTE: when there are few cases in the cases table, these indices may not be worthwhile + String casesIdx1 = "CREATE INDEX IF NOT EXISTS cases_org_id ON cases (org_id)"; + String casesIdx2 = "CREATE INDEX IF NOT EXISTS cases_case_uid ON cases (case_uid)"; + + StringBuilder createDataSourcesTable = new StringBuilder(); + createDataSourcesTable.append("CREATE TABLE IF NOT EXISTS data_sources ("); + createDataSourcesTable.append("id integer primary key autoincrement NOT NULL,"); + createDataSourcesTable.append("device_id text NOT NULL,"); + createDataSourcesTable.append("name text NOT NULL,"); + createDataSourcesTable.append("CONSTRAINT device_id_unique UNIQUE(device_id)"); + createDataSourcesTable.append(")"); + + String dataSourceIdx1 = "CREATE INDEX IF NOT EXISTS data_sources_name ON data_sources (name)"; + + StringBuilder createGlobalReferenceSetsTable = new StringBuilder(); + createGlobalReferenceSetsTable.append("CREATE TABLE IF NOT EXISTS global_reference_sets ("); + createGlobalReferenceSetsTable.append("id integer primary key autoincrement NOT NULL,"); + createGlobalReferenceSetsTable.append("org_id integer,"); + createGlobalReferenceSetsTable.append("set_name text NOT NULL,"); + createGlobalReferenceSetsTable.append("version text NOT NULL,"); + createGlobalReferenceSetsTable.append("import_date text NOT NULL,"); + createGlobalReferenceSetsTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null"); + createGlobalReferenceSetsTable.append(")"); + + String globalReferenceSetsIdx1 = "CREATE INDEX IF NOT EXISTS global_reference_sets_org_id ON global_reference_sets (org_id)"; + + StringBuilder createGlobalFilesTable = new StringBuilder(); + createGlobalFilesTable.append("CREATE TABLE IF NOT EXISTS global_files ("); + createGlobalFilesTable.append("id integer primary key autoincrement NOT NULL,"); + createGlobalFilesTable.append("global_reference_set_id integer,"); + createGlobalFilesTable.append("value text NOT NULL,"); + createGlobalFilesTable.append("known_status text NOT NULL,"); + createGlobalFilesTable.append("comment text NOT NULL,"); + createGlobalFilesTable.append("CONSTRAINT global_files_multi_unique UNIQUE(global_reference_set_id, value)"); + createGlobalFilesTable.append("foreign key (global_reference_set_id) references global_reference_sets(id) on update set null on delete set null"); + createGlobalFilesTable.append(")"); + + String globalFilesIdx1 = "CREATE INDEX IF NOT EXISTS global_files_value ON global_files (value)"; + String globalFilesIdx2 = "CREATE INDEX IF NOT EXISTS global_files_value_known_status ON global_files (value, known_status)"; + + StringBuilder createArtifactTypesTable = new StringBuilder(); + createArtifactTypesTable.append("CREATE TABLE IF NOT EXISTS artifact_types ("); + createArtifactTypesTable.append("id integer primary key autoincrement NOT NULL,"); + createArtifactTypesTable.append("name text NOT NULL,"); + createArtifactTypesTable.append("supported integer NOT NULL,"); + createArtifactTypesTable.append("enabled integer NOT NULL,"); + createArtifactTypesTable.append("CONSTRAINT artifact_type_name_unique UNIQUE (name)"); + createArtifactTypesTable.append(")"); + + // NOTE: there are API methods that query by one of: name, supported, or enabled. + // Only name is currently implemented, but, there will only be a small number + // of artifact_types, so there is no benefit to having any indices. + StringBuilder createArtifactInstancesTableTemplate = new StringBuilder(); + createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s_instances ("); + createArtifactInstancesTableTemplate.append("id integer primary key autoincrement NOT NULL,"); + createArtifactInstancesTableTemplate.append("case_id integer,"); + createArtifactInstancesTableTemplate.append("data_source_id integer,"); + createArtifactInstancesTableTemplate.append("value text NOT NULL,"); + createArtifactInstancesTableTemplate.append("file_path text NOT NULL,"); + createArtifactInstancesTableTemplate.append("known_status text NOT NULL,"); + createArtifactInstancesTableTemplate.append("comment text NOT NULL,"); + createArtifactInstancesTableTemplate.append("CONSTRAINT %s_instances_multi_unique UNIQUE(case_id, data_source_id, value, file_path),"); + createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) on update set null on delete set null,"); + createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) on update set null on delete set null"); + createArtifactInstancesTableTemplate.append(")"); + + // TODO: do we need any more indices? + String instancesIdx1 = "CREATE INDEX IF NOT EXISTS %s_instances_case_id ON %s_instances (case_id)"; + String instancesIdx2 = "CREATE INDEX IF NOT EXISTS %s_instances_data_source_id ON %s_instances (data_source_id)"; + String instancesIdx3 = "CREATE INDEX IF NOT EXISTS %s_instances_value ON %s_instances (value)"; + String instancesIdx4 = "CREATE INDEX IF NOT EXISTS %s_instances_value_known_status ON %s_instances (value, known_status)"; + + StringBuilder createDbInfoTable = new StringBuilder(); + createDbInfoTable.append("CREATE TABLE IF NOT EXISTS db_info ("); + createDbInfoTable.append("id integer primary key NOT NULL,"); + createDbInfoTable.append("name text NOT NULL,"); + createDbInfoTable.append("value text NOT NULL"); + createDbInfoTable.append(")"); + + // NOTE: the db_info table currenly only has 1 row, so having an index + // provides no benefit. + + Connection conn = null; + try { + conn = getEphemeralConnection(); + if (null == conn) { + return false; + } + Statement stmt = conn.createStatement(); + stmt.execute(PRAGMA_JOURNAL_WAL); + stmt.execute(PRAGMA_SYNC_OFF); + stmt.execute(PRAGMA_READ_UNCOMMITTED_TRUE); + stmt.execute(PRAGMA_ENCODING_UTF8); + stmt.execute(PRAGMA_PAGE_SIZE_4096); + stmt.execute(PRAGMA_FOREIGN_KEYS_ON); + + stmt.execute(createOrganizationsTable.toString()); + + stmt.execute(createCasesTable.toString()); + stmt.execute(casesIdx1); + stmt.execute(casesIdx2); + + stmt.execute(createDataSourcesTable.toString()); + stmt.execute(dataSourceIdx1); + + stmt.execute(createGlobalReferenceSetsTable.toString()); + stmt.execute(globalReferenceSetsIdx1); + + stmt.execute(createGlobalFilesTable.toString()); + stmt.execute(globalFilesIdx1); + stmt.execute(globalFilesIdx2); + + stmt.execute(createArtifactTypesTable.toString()); + + stmt.execute(createDbInfoTable.toString()); + + // Create a separate table for each artifact type + List DEFAULT_ARTIFACT_TYPES = EamArtifact.getDefaultArtifactTypes(); + + String type_name; + for (EamArtifact.Type type : DEFAULT_ARTIFACT_TYPES) { + type_name = type.getName(); + stmt.execute(String.format(createArtifactInstancesTableTemplate.toString(), type_name, type_name)); + stmt.execute(String.format(instancesIdx1, type_name, type_name)); + stmt.execute(String.format(instancesIdx2, type_name, type_name)); + stmt.execute(String.format(instancesIdx3, type_name, type_name)); + stmt.execute(String.format(instancesIdx4, type_name, type_name)); + } + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, "Error initializing db schema.", ex); // NON-NLS + return false; + } finally { + EamDbUtil.closeConnection(conn); + } return true; } + public boolean insertDefaultDatabaseContent() { + Connection conn = getEphemeralConnection(); + if (null == conn) { + return false; + } + + boolean result = EamDbUtil.insertDefaultArtifactTypes(conn) + && EamDbUtil.insertSchemaVersion(conn); + EamDbUtil.closeConnection(conn); + return result; + } + public boolean isChanged() { String dbNameString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.sqlite.dbName"); // NON-NLS String dbDirectoryString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.sqlite.dbDirectory"); // NON-NLS @@ -184,20 +419,6 @@ public final class SqliteEamDbSettings { || !Integer.toString(bulkThreshold).equals(bulkThresholdString); } - /** - * @return the enabled - */ - public boolean isEnabled() { - return enabled; - } - - /** - * @param enabled the enabled to set - */ - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - /** * @return the dbName */ @@ -211,11 +432,13 @@ public final class SqliteEamDbSettings { * @param dbName the dbName to set */ public void setDbName(String dbName) throws EamDbException { - if (dbName != null && !dbName.isEmpty()) { - this.dbName = dbName; - } else { - throw new EamDbException("Error invalid file name for database. Cannot be null or empty."); // NON-NLS + if (dbName == null || dbName.isEmpty()) { + throw new EamDbException("Invalid database file name. Cannot be null or empty."); // NON-NLS + } else if (!Pattern.matches(DB_NAMES_REGEX, dbName)) { + throw new EamDbException("Invalid database file name. Name must start with a letter and can only contain letters, numbers, and '_'."); // NON-NLS } + + this.dbName = dbName; } /** @@ -232,7 +455,7 @@ public final class SqliteEamDbSettings { if (bulkThreshold > 0) { this.bulkThreshold = bulkThreshold; } else { - throw new EamDbException("Error invalid bulk threshold for database connection."); // NON-NLS + throw new EamDbException("Invalid bulk threshold for database connection."); // NON-NLS } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/BadFileTagRunner.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/BadFileTagRunner.java index 3bbbb1aebf..1355bbef7e 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/BadFileTagRunner.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/BadFileTagRunner.java @@ -42,7 +42,7 @@ public class BadFileTagRunner implements Runnable { @Override public void run() { - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { LOGGER.log(Level.WARNING, "Enterprise artifacts manager database not configured"); // NON-NLS return; } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/CaseEventListener.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/CaseEventListener.java index 053eeebbc3..039e9a8867 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/CaseEventListener.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/CaseEventListener.java @@ -61,7 +61,7 @@ public class CaseEventListener implements PropertyChangeListener { EamDb dbManager = EamDb.getInstance(); switch (Case.Events.valueOf(evt.getPropertyName())) { case CONTENT_TAG_ADDED: { - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { return; } @@ -125,7 +125,7 @@ public class CaseEventListener implements PropertyChangeListener { break; case BLACKBOARD_ARTIFACT_TAG_ADDED: { - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { return; } @@ -157,7 +157,7 @@ public class CaseEventListener implements PropertyChangeListener { break; case DATA_SOURCE_ADDED: { - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { break; } @@ -214,7 +214,7 @@ public class CaseEventListener implements PropertyChangeListener { "", ""); - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { break; } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/IngestEventsListener.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/IngestEventsListener.java index bcd1f3abeb..9066d960d5 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/IngestEventsListener.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/IngestEventsListener.java @@ -78,7 +78,7 @@ public class IngestEventsListener { EamDb dbManager = EamDb.getInstance(); switch (IngestManager.IngestModuleEvent.valueOf(evt.getPropertyName())) { case DATA_ADDED: { - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { return; } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/NewArtifactsRunner.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/NewArtifactsRunner.java index 79762b75a6..a8eaa8fd3d 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/NewArtifactsRunner.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/NewArtifactsRunner.java @@ -45,7 +45,7 @@ public class NewArtifactsRunner implements Runnable { @Override public void run() { - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { LOGGER.log(Level.WARNING, "Enterprise artifacts manager database not configured"); // NON-NLS return; } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/ingestmodule/IngestModule.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/ingestmodule/IngestModule.java index 72fdf1762b..6937f5aca1 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/ingestmodule/IngestModule.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/ingestmodule/IngestModule.java @@ -29,7 +29,6 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.core.RuntimeProperties; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.ingest.FileIngestModule; import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestMessage; @@ -69,8 +68,7 @@ class IngestModule implements FileIngestModule { @Override public ProcessResult process(AbstractFile af) { - if (Boolean.parseBoolean(ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.enabled")) == false - || EamDb.getInstance().isEnabled() == false) { + if (EamDb.isEnabled() == false) { /* * Not signaling an error for now. This is a workaround for the way * all newly didscovered ingest modules are automatically anabled. @@ -152,8 +150,7 @@ class IngestModule implements FileIngestModule { @Override public void shutDown() { - if (Boolean.parseBoolean(ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.enabled")) == false - || EamDb.getInstance().isEnabled() == false) { + if (EamDb.isEnabled() == false) { /* * Not signaling an error for now. This is a workaround for the way * all newly didscovered ingest modules are automatically anabled. @@ -187,8 +184,7 @@ class IngestModule implements FileIngestModule { }) @Override public void startUp(IngestJobContext context) throws IngestModuleException { - if (Boolean.parseBoolean(ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.enabled")) == false - || EamDb.getInstance().isEnabled() == false) { + if (EamDb.isEnabled() == false) { /* * Not throwing the customary exception for now. This is a * workaround for the way all newly didscovered ingest modules are diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties index ccb83b2e46..8811aa8c49 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties @@ -13,11 +13,9 @@ EamPostgresSettingsDialog.lbUserPassword.text=User Password : EamPostgresSettingsDialog.lbUserName.text=User Name : EamPostgresSettingsDialog.bnCancel.text=Cancel EamPostgresSettingsDialog.lbPort.text=Port : -EamPostgresSettingsDialog.bnSave.text=Save EamPostgresSettingsDialog.lbHostName.text=Host Name / IP : EamPostgresSettingsDialog.bnTestConnection.text=Test Connection EamPostgresSettingsDialog.lbDatabaseName.text=Database name : -EamSqliteSettingsDialog.bnSave.text=Save EamSqliteSettingsDialog.bnCancel.text=Cancel EamSqliteSettingsDialog.lbTestDatabase.text= EamSqliteSettingsDialog.bnTestDatabase.text=Test Connection @@ -44,14 +42,11 @@ ImportHashDatabaseDialog.bnNewOrganization.text=Add New Organization ImportHashDatabaseDialog.tfDatabaseName.tooltip=Name for this database ImportHashDatabaseDialog.tfDatabaseVersion.tooltip.text=Database Version Number GlobalSettingsPanel.bnImportDatabase.actionCommand= -GlobalSettingsPanel.cbEnableEnterpriseArtifactsManager.text=Enable Enterprise Artifacts Manager GlobalSettingsPanel.bnManageTypes.text=Manage Artifact Types GlobalSettingsPanel.bnManageTags.actionCommand= GlobalSettingsPanel.bnManageTags.toolTipText= GlobalSettingsPanel.bnManageTags.text=Manage Tags GlobalSettingsPanel.tbOops.text= -GlobalSettingsPanel.bnConfigureDatabaseSettings.text=Configure -GlobalSettingsPanel.lbDatabasePlatform.text=Enable Database Platform : GlobalSettingsPanel.lbDatabaseSettings.text=Database Settings GlobalSettingsPanel.bnImportDatabase.label=Import Hash Database AddNewOrganizationDialog.lbPocPhone.text=Phone: @@ -68,3 +63,28 @@ ManageArtifactTypesDialog.cancelButton.text=Cancel ManageArtifactTypesDialog.okButton.text=OK ManageArtifactTypesDialog.lbWarningMsg.text=Warning Message ManageArtifactTypesDialog.taInstructionsMsg.text=Select one or more artifact types to store in the database and use for correlation during Ingest. +EamSqliteSettingsDialog.bnOk.text=OK +EamPostgresSettingsDialog.bnSave.text=Save +EamDbSettingsDialog.pnDatabaseConnectionSettings.border.title=Database Settings +EamDbSettingsDialog.rdioBnPostgreSQL.text=PostgreSQL +EamDbSettingsDialog.rdioBnSQLite.text=SQLite +EamDbSettingsDialog.bnDatabasePathFileOpen.text=Open... +EamDbSettingsDialog.tfDatabasePath.toolTipText=Filename and path to store SQLite db file +EamDbSettingsDialog.tfDatabasePath.text= +EamDbSettingsDialog.lbDatabasePath.text=Database Path : +EamDbSettingsDialog.rdioBnDisabled.text=Disabled +EamDbSettingsDialog.bnCancel.text=Cancel +EamDbSettingsDialog.bnOk.text=OK +EamDbSettingsDialog.bnTest.text=Test +EamDbSettingsDialog.lbHostName.text=Host Name / IP : +EamDbSettingsDialog.lbDatabaseName.text=Database name : +EamDbSettingsDialog.lbUserPassword.text=User Password : +EamDbSettingsDialog.lbUserName.text=User Name : +EamDbSettingsDialog.lbPort.text=Port : +EamDbSettingsDialog.bnCreateDb.text=Create +EamDbSettingsDialog.pnSetupGuidance.border.title=Setup Guidance +GlobalSettingsPanel.pnDatabaseConfiguration.title=Database Configuration +GlobalSettingsPanel.lbDbPlatformTypeLabel.text=Type: +GlobalSettingsPanel.lbDbNameLabel.text=Name: +GlobalSettingsPanel.bnDbConfigure.text=Configure +GlobalSettingsPanel.lbDbLocationLabel.text=Location: diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamDbSettingsDialog.form b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamDbSettingsDialog.form new file mode 100644 index 0000000000..3a43033eca --- /dev/null +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamDbSettingsDialog.form @@ -0,0 +1,489 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamDbSettingsDialog.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamDbSettingsDialog.java new file mode 100644 index 0000000000..4f95216843 --- /dev/null +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamDbSettingsDialog.java @@ -0,0 +1,932 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.optionspanel; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Toolkit; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.logging.Level; +import javax.swing.ImageIcon; +import javax.swing.JDialog; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JTextField; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import org.netbeans.spi.options.OptionsPanelController; +import org.openide.util.ImageUtilities; +import org.openide.util.NbBundle.Messages; +import org.openide.windows.WindowManager; +import org.sleuthkit.autopsy.corecomponents.TextPrompt; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb; +import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException; +import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbPlatformEnum; +import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.PostgresEamDbSettings; +import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.SqliteEamDbSettings; + +/** + * + * @author nick + */ +public class EamDbSettingsDialog extends JDialog { + private static final Logger LOGGER = Logger.getLogger(EamDbSettingsDialog.class.getName()); + private final Collection textBoxes; + private final TextBoxChangedListener textBoxChangedListener; + private final ImageIcon goodIcon; + private final ImageIcon badIcon; + + private final PostgresEamDbSettings dbSettingsPostgres; + private final SqliteEamDbSettings dbSettingsSqlite; + private DatabaseTestResult testingStatus; + private EamDbPlatformEnum selectedPlatform; + + /** + * Creates new form EamDbSettingsDialog + */ + @Messages({"EamDbSettingsDialog.title.text=Enterprise Artifacts Manager Settings"}) + public EamDbSettingsDialog() { + super((JFrame) WindowManager.getDefault().getMainWindow(), + Bundle.EamDbSettingsDialog_title_text(), + true); // NON-NLS + + textBoxes = new ArrayList<>(); + textBoxChangedListener = new TextBoxChangedListener(); + goodIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/images/good.png", false)); // NON-NLS + badIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/images/bad.png", false)); // NON-NLS + + dbSettingsPostgres = new PostgresEamDbSettings(); + dbSettingsSqlite = new SqliteEamDbSettings(); + selectedPlatform = EamDbPlatformEnum.getSelectedPlatform(); + + initComponents(); + customizeComponents(); + valid(); + display(); + } + + /** + * 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") + // //GEN-BEGIN:initComponents + private void initComponents() { + + bnGrpDatabasePlatforms = new javax.swing.ButtonGroup(); + fcDatabasePath = new javax.swing.JFileChooser(); + pnDatabaseConnectionSettings = new javax.swing.JPanel(); + pnSQLiteSettings = new javax.swing.JPanel(); + lbDatabasePath = new javax.swing.JLabel(); + tfDatabasePath = new javax.swing.JTextField(); + bnDatabasePathFileOpen = new javax.swing.JButton(); + pnPostgreSQLSettings = new javax.swing.JPanel(); + lbHostName = new javax.swing.JLabel(); + lbPort = new javax.swing.JLabel(); + lbUserName = new javax.swing.JLabel(); + lbUserPassword = new javax.swing.JLabel(); + lbDatabaseName = new javax.swing.JLabel(); + tbDbHostname = new javax.swing.JTextField(); + tbDbPort = new javax.swing.JTextField(); + tbDbName = new javax.swing.JTextField(); + tbDbUsername = new javax.swing.JTextField(); + jpDbPassword = new javax.swing.JPasswordField(); + rdioBnSQLite = new javax.swing.JRadioButton(); + rdioBnPostgreSQL = new javax.swing.JRadioButton(); + rdioBnDisabled = new javax.swing.JRadioButton(); + pnButtons = new javax.swing.JPanel(); + bnCancel = new javax.swing.JButton(); + bnOk = new javax.swing.JButton(); + bnTest = new javax.swing.JButton(); + bnCreateDb = new javax.swing.JButton(); + lbTestIcon = new javax.swing.JLabel(); + lbCreateIcon = new javax.swing.JLabel(); + pnSetupGuidance = new javax.swing.JPanel(); + jScrollPane1 = new javax.swing.JScrollPane(); + taSetupGuidance = new javax.swing.JTextArea(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + pnDatabaseConnectionSettings.setBorder(javax.swing.BorderFactory.createTitledBorder(null, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.pnDatabaseConnectionSettings.border.title"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 0, 12))); // NOI18N + pnDatabaseConnectionSettings.setName(""); // NOI18N + + pnSQLiteSettings.setBorder(javax.swing.BorderFactory.createEtchedBorder()); + + org.openide.awt.Mnemonics.setLocalizedText(lbDatabasePath, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.lbDatabasePath.text")); // NOI18N + + tfDatabasePath.setText(org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.tfDatabasePath.text")); // NOI18N + tfDatabasePath.setToolTipText(org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.tfDatabasePath.toolTipText")); // NOI18N + tfDatabasePath.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + tfDatabasePathFocusLost(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(bnDatabasePathFileOpen, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.bnDatabasePathFileOpen.text")); // NOI18N + bnDatabasePathFileOpen.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + bnDatabasePathFileOpenActionPerformed(evt); + } + }); + + javax.swing.GroupLayout pnSQLiteSettingsLayout = new javax.swing.GroupLayout(pnSQLiteSettings); + pnSQLiteSettings.setLayout(pnSQLiteSettingsLayout); + pnSQLiteSettingsLayout.setHorizontalGroup( + pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnSQLiteSettingsLayout.createSequentialGroup() + .addContainerGap() + .addComponent(lbDatabasePath) + .addGap(18, 18, 18) + .addComponent(tfDatabasePath, javax.swing.GroupLayout.PREFERRED_SIZE, 343, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(bnDatabasePathFileOpen) + .addContainerGap()) + ); + pnSQLiteSettingsLayout.setVerticalGroup( + pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnSQLiteSettingsLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lbDatabasePath, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(tfDatabasePath, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(bnDatabasePathFileOpen)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + pnPostgreSQLSettings.setBorder(javax.swing.BorderFactory.createEtchedBorder()); + + org.openide.awt.Mnemonics.setLocalizedText(lbHostName, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.lbHostName.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(lbPort, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.lbPort.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(lbUserName, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.lbUserName.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(lbUserPassword, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.lbUserPassword.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(lbDatabaseName, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.lbDatabaseName.text")); // NOI18N + + javax.swing.GroupLayout pnPostgreSQLSettingsLayout = new javax.swing.GroupLayout(pnPostgreSQLSettings); + pnPostgreSQLSettings.setLayout(pnPostgreSQLSettingsLayout); + pnPostgreSQLSettingsLayout.setHorizontalGroup( + pnPostgreSQLSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnPostgreSQLSettingsLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnPostgreSQLSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lbHostName) + .addComponent(lbPort) + .addComponent(lbDatabaseName) + .addComponent(lbUserName) + .addComponent(lbUserPassword)) + .addGap(18, 18, 18) + .addGroup(pnPostgreSQLSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(tbDbUsername, javax.swing.GroupLayout.DEFAULT_SIZE, 439, Short.MAX_VALUE) + .addComponent(tbDbName) + .addComponent(tbDbPort) + .addComponent(tbDbHostname) + .addComponent(jpDbPassword)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + pnPostgreSQLSettingsLayout.setVerticalGroup( + pnPostgreSQLSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnPostgreSQLSettingsLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnPostgreSQLSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(tbDbHostname, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lbHostName, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnPostgreSQLSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(tbDbPort) + .addComponent(lbPort, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnPostgreSQLSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(tbDbName) + .addComponent(lbDatabaseName, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnPostgreSQLSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(tbDbUsername) + .addComponent(lbUserName, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnPostgreSQLSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lbUserPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jpDbPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(19, Short.MAX_VALUE)) + ); + + org.openide.awt.Mnemonics.setLocalizedText(rdioBnSQLite, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.rdioBnSQLite.text")); // NOI18N + rdioBnSQLite.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + rdioBnSQLiteActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(rdioBnPostgreSQL, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.rdioBnPostgreSQL.text")); // NOI18N + rdioBnPostgreSQL.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + rdioBnPostgreSQLActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(rdioBnDisabled, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.rdioBnDisabled.text")); // NOI18N + rdioBnDisabled.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + rdioBnDisabledActionPerformed(evt); + } + }); + + javax.swing.GroupLayout pnDatabaseConnectionSettingsLayout = new javax.swing.GroupLayout(pnDatabaseConnectionSettings); + pnDatabaseConnectionSettings.setLayout(pnDatabaseConnectionSettingsLayout); + pnDatabaseConnectionSettingsLayout.setHorizontalGroup( + pnDatabaseConnectionSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnDatabaseConnectionSettingsLayout.createSequentialGroup() + .addComponent(rdioBnPostgreSQL) + .addGap(0, 0, Short.MAX_VALUE)) + .addGroup(pnDatabaseConnectionSettingsLayout.createSequentialGroup() + .addGroup(pnDatabaseConnectionSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(rdioBnSQLite) + .addComponent(rdioBnDisabled)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(pnDatabaseConnectionSettingsLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnDatabaseConnectionSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(pnSQLiteSettings, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pnPostgreSQLSettings, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + ); + pnDatabaseConnectionSettingsLayout.setVerticalGroup( + pnDatabaseConnectionSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnDatabaseConnectionSettingsLayout.createSequentialGroup() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(rdioBnDisabled) + .addGap(13, 13, 13) + .addComponent(rdioBnSQLite) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pnSQLiteSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(12, 12, 12) + .addComponent(rdioBnPostgreSQL) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pnPostgreSQLSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(329, 329, 329)) + ); + + org.openide.awt.Mnemonics.setLocalizedText(bnCancel, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.bnCancel.text")); // NOI18N + bnCancel.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + bnCancelActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(bnOk, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.bnOk.text")); // NOI18N + bnOk.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + bnOkActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(bnTest, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.bnTest.text")); // NOI18N + bnTest.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + bnTestActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(bnCreateDb, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.bnCreateDb.text")); // NOI18N + bnCreateDb.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + bnCreateDbActionPerformed(evt); + } + }); + + javax.swing.GroupLayout pnButtonsLayout = new javax.swing.GroupLayout(pnButtons); + pnButtons.setLayout(pnButtonsLayout); + pnButtonsLayout.setHorizontalGroup( + pnButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnButtonsLayout.createSequentialGroup() + .addContainerGap() + .addComponent(bnTest) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lbTestIcon, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, 18) + .addComponent(bnCreateDb) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lbCreateIcon, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(bnOk) + .addGap(11, 11, 11) + .addComponent(bnCancel) + .addContainerGap()) + ); + pnButtonsLayout.setVerticalGroup( + pnButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnButtonsLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(pnButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lbCreateIcon, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(lbTestIcon, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(pnButtonsLayout.createSequentialGroup() + .addGroup(pnButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(bnOk) + .addComponent(bnCancel) + .addComponent(bnTest) + .addComponent(bnCreateDb)) + .addGap(0, 0, Short.MAX_VALUE))) + .addContainerGap()) + ); + + pnSetupGuidance.setBorder(javax.swing.BorderFactory.createTitledBorder(null, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.pnSetupGuidance.border.title"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 0, 12))); // NOI18N + + jScrollPane1.setBorder(null); + + taSetupGuidance.setEditable(false); + taSetupGuidance.setBackground(new java.awt.Color(240, 240, 240)); + taSetupGuidance.setColumns(20); + taSetupGuidance.setFont(new java.awt.Font("Monospaced", 0, 12)); // NOI18N + taSetupGuidance.setLineWrap(true); + taSetupGuidance.setRows(3); + taSetupGuidance.setTabSize(4); + taSetupGuidance.setWrapStyleWord(true); + taSetupGuidance.setAutoscrolls(false); + taSetupGuidance.setBorder(null); + taSetupGuidance.setRequestFocusEnabled(false); + taSetupGuidance.setVerifyInputWhenFocusTarget(false); + jScrollPane1.setViewportView(taSetupGuidance); + + javax.swing.GroupLayout pnSetupGuidanceLayout = new javax.swing.GroupLayout(pnSetupGuidance); + pnSetupGuidance.setLayout(pnSetupGuidanceLayout); + pnSetupGuidanceLayout.setHorizontalGroup( + pnSetupGuidanceLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnSetupGuidanceLayout.createSequentialGroup() + .addContainerGap() + .addComponent(jScrollPane1) + .addContainerGap()) + ); + pnSetupGuidanceLayout.setVerticalGroup( + pnSetupGuidanceLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnSetupGuidanceLayout.createSequentialGroup() + .addContainerGap() + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(pnSetupGuidance, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pnDatabaseConnectionSettings, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pnButtons, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(pnSetupGuidance, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pnDatabaseConnectionSettings, javax.swing.GroupLayout.PREFERRED_SIZE, 348, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pnButtons, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0)) + ); + + pack(); + }// //GEN-END:initComponents + + private void customizeComponents() { + bnGrpDatabasePlatforms.add(rdioBnDisabled); + bnGrpDatabasePlatforms.add(rdioBnPostgreSQL); + bnGrpDatabasePlatforms.add(rdioBnSQLite); + + switch (selectedPlatform) { + case POSTGRESQL: + rdioBnPostgreSQL.setSelected(true); + testingStatus = DatabaseTestResult.UNTESTED; + updatePostgresFields(true); + updateSqliteFields(false); + break; + case SQLITE: + rdioBnSQLite.setSelected(true); + testingStatus = DatabaseTestResult.UNTESTED; + updatePostgresFields(false); + updateSqliteFields(true); + break; + default: + rdioBnDisabled.setSelected(true); + testingStatus = DatabaseTestResult.TESTEDOK; + updatePostgresFields(false); + updateSqliteFields(false); + break; + } + + setTextPrompts(); + setTextBoxListeners(); + lbTestIcon.setIcon(null); + } + + private void display() { + Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); + setLocation((screenDimension.width - getSize().width) / 2, (screenDimension.height - getSize().height) / 2); + setVisible(true); + } + private void setGuidanceMessage(String message, boolean isError) { + taSetupGuidance.setText(message); + if (isError) { + taSetupGuidance.setForeground(new Color(255, 102, 102)); // light red color + } else { + taSetupGuidance.setForeground(new Color(0, 0, 0)); // black color + } + } + + private void clearIcons() { + lbTestIcon.setIcon(null); + lbCreateIcon.setIcon(null); + } + + @Messages({"EamDbSettingsDialog.chooserPath.failedToGetDbPathMsg=Selected database path is invalid. Try again."}) + private void bnDatabasePathFileOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnDatabasePathFileOpenActionPerformed + fcDatabasePath.setCurrentDirectory(new File(dbSettingsSqlite.getDbDirectory())); + fcDatabasePath.setSelectedFile(new File(dbSettingsSqlite.getFileNameWithPath())); + if (fcDatabasePath.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { + File databaseFile = fcDatabasePath.getSelectedFile(); + try { + String fullPath = databaseFile.getCanonicalPath(); + if (!fullPath.endsWith(".db")) { + fullPath = fullPath + ".db"; // NON-NLS + } + tfDatabasePath.setText(fullPath); + valid(); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, "Failed to get path of selected database file", ex); // NON-NLS + setGuidanceMessage(Bundle.EamDbSettingsDialog_chooserPath_failedToGetDbPathMsg(), true); + } + } + }//GEN-LAST:event_bnDatabasePathFileOpenActionPerformed + + private void bnTestActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnTestActionPerformed + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + + switch (selectedPlatform) { + case POSTGRESQL: + if (dbSettingsPostgres.verifyConnection()) { + if (dbSettingsPostgres.verifyDatabaseExists() + && dbSettingsPostgres.verifyDatabaseSchema()) { + testingStatus = DatabaseTestResult.TESTEDOK; + } else { + testingStatus = DatabaseTestResult.SCHEMA_INVALID; + } + } else { + testingStatus = DatabaseTestResult.CONNECTION_FAILED; + } + break; + case SQLITE: + if (dbSettingsSqlite.dbDirectoryExists() + && dbSettingsSqlite.verifyConnection()) { + if (dbSettingsSqlite.verifyDatabaseSchema()) { + testingStatus = DatabaseTestResult.TESTEDOK; + } else { + testingStatus = DatabaseTestResult.SCHEMA_INVALID; + } + } else { + testingStatus = DatabaseTestResult.SCHEMA_INVALID; + } + break; + } + + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + if (testingStatus == DatabaseTestResult.TESTEDOK) { + lbTestIcon.setIcon(goodIcon); + } else { + lbTestIcon.setIcon(badIcon); + } + valid(); + }//GEN-LAST:event_bnTestActionPerformed + + @Messages({"EamDbSettingsDialog.creation.failed=Database initialization failed."}) + private void bnCreateDbActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnCreateDbActionPerformed + + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + clearIcons(); + boolean result = false; + switch (selectedPlatform) { + case POSTGRESQL: + if (!dbSettingsPostgres.verifyDatabaseExists()) { + dbSettingsPostgres.createDatabase(); + } + result = dbSettingsPostgres.initializeDatabaseSchema() + && dbSettingsPostgres.insertDefaultDatabaseContent(); + + break; + case SQLITE: + if (!dbSettingsSqlite.dbDirectoryExists()) { + dbSettingsSqlite.createDbDirectory(); + } + result = dbSettingsSqlite.initializeDatabaseSchema() + && dbSettingsSqlite.insertDefaultDatabaseContent(); + break; + } + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + if (false == result) { + setGuidanceMessage(Bundle.EamDbSettingsDialog_creation_failed(), true); + lbCreateIcon.setIcon(badIcon); + } else { + testingStatus = DatabaseTestResult.TESTEDOK; + lbCreateIcon.setIcon(goodIcon); + valid(); + } + }//GEN-LAST:event_bnCreateDbActionPerformed + + private void bnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOkActionPerformed + EamDbPlatformEnum.setSelectedPlatform(selectedPlatform.name()); + EamDbPlatformEnum.saveSelectedPlatform(); + switch (selectedPlatform) { + case POSTGRESQL: + dbSettingsPostgres.saveSettings(); + EamDb.getInstance().updateSettings(); + break; + case SQLITE: + dbSettingsSqlite.saveSettings(); + EamDb.getInstance().updateSettings(); + break; + case DISABLED: + break; + } + + dispose(); + }//GEN-LAST:event_bnOkActionPerformed + + private void bnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnCancelActionPerformed + dispose(); + }//GEN-LAST:event_bnCancelActionPerformed + + private void rdioBnDisabledActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rdioBnDisabledActionPerformed + selectedPlatform = EamDbPlatformEnum.DISABLED; + testingStatus = DatabaseTestResult.TESTEDOK; + + updateSqliteFields(false); + updatePostgresFields(false); + }//GEN-LAST:event_rdioBnDisabledActionPerformed + + + private void rdioBnPostgreSQLActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rdioBnPostgreSQLActionPerformed + selectedPlatform = EamDbPlatformEnum.POSTGRESQL; + testingStatus = DatabaseTestResult.UNTESTED; + + updateSqliteFields(false); + updatePostgresFields(true); + }//GEN-LAST:event_rdioBnPostgreSQLActionPerformed + + private void rdioBnSQLiteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rdioBnSQLiteActionPerformed + selectedPlatform = EamDbPlatformEnum.SQLITE; + testingStatus = DatabaseTestResult.UNTESTED; + + updateSqliteFields(true); + updatePostgresFields(false); + + }//GEN-LAST:event_rdioBnSQLiteActionPerformed + + private void tfDatabasePathFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_tfDatabasePathFocusLost + String fullPath = tfDatabasePath.getText(); + if (!fullPath.endsWith(".db")) { + fullPath = fullPath + ".db"; // NON-NLS + } + tfDatabasePath.setText(fullPath); + }//GEN-LAST:event_tfDatabasePathFocusLost + + /** + * Update the fields for the Postgres platform depending on whether the + * Postgres radioButton is enabled. + * + * @param enabled + */ + private void updatePostgresFields(boolean enabled) { + tbDbHostname.setText(enabled ? dbSettingsPostgres.getHost() : ""); + tbDbHostname.setEnabled(enabled); + tbDbPort.setText(enabled ? Integer.toString(dbSettingsPostgres.getPort()) : ""); + tbDbPort.setEnabled(enabled); + tbDbName.setText(enabled ? dbSettingsPostgres.getDbName() : ""); + tbDbName.setEnabled(enabled); + tbDbUsername.setText(enabled ? dbSettingsPostgres.getUserName() : ""); + tbDbUsername.setEnabled(enabled); + jpDbPassword.setText(enabled ? dbSettingsPostgres.getPassword() : ""); + jpDbPassword.setEnabled(enabled); + } + + /** + * Update the fields for the SQLite platform depending on whether the + * SQLite radioButton is enabled. + * + * @param enabled + */ + private void updateSqliteFields(boolean enabled) { + tfDatabasePath.setText(enabled ? dbSettingsSqlite.getFileNameWithPath() : ""); + tfDatabasePath.setEnabled(enabled); + bnDatabasePathFileOpen.setEnabled(enabled); + } + + /** + * Add text prompts to all of the text fields. + */ + @Messages({"EamDbSettingsDialog.textPrompt.hostnameOrIP=Hostname or IP Address", + "EamDbSettingsDialog.textPrompt.port=Port Number", + "EamDbSettingsDialog.textPrompt.dbName=Database Name", + "EamDbSettingsDialog.textPrompt.user=Database User", + "EamDbSettingsDialog.textPrompt.password=Database User's Password"}) + private void setTextPrompts() { + Collection textPrompts = new ArrayList<>(); + textPrompts.add(new TextPrompt(Bundle.EamDbSettingsDialog_textPrompt_hostnameOrIP(), tbDbHostname)); + textPrompts.add(new TextPrompt(Bundle.EamDbSettingsDialog_textPrompt_port(), tbDbPort)); + textPrompts.add(new TextPrompt(Bundle.EamDbSettingsDialog_textPrompt_dbName(), tbDbName)); + textPrompts.add(new TextPrompt(Bundle.EamDbSettingsDialog_textPrompt_user(), tbDbUsername)); + configureTextPrompts(textPrompts); + } + + /** + * Register for notifications when the text boxes get updated. + */ + private void setTextBoxListeners() { + textBoxes.add(tfDatabasePath); + textBoxes.add(tbDbHostname); + textBoxes.add(tbDbPort); + textBoxes.add(tbDbName); + textBoxes.add(tbDbUsername); + textBoxes.add(jpDbPassword); + addDocumentListeners(textBoxes, textBoxChangedListener); + } + + /** + * Sets the foreground color and transparency of a collection of text + * prompts. + * + * @param textPrompts The text prompts to configure. + */ + private static void configureTextPrompts(Collection textPrompts) { + float alpha = 0.9f; // Mostly opaque + for (TextPrompt textPrompt : textPrompts) { + textPrompt.setForeground(Color.LIGHT_GRAY); + textPrompt.changeAlpha(alpha); + } + } + + /** + * Adds a change listener to a collection of text fields. + * + * @param textFields The text fields. + * @param listener The change listener. + */ + private static void addDocumentListeners(Collection textFields, TextBoxChangedListener listener) { + textFields.forEach((textField) -> { + textField.getDocument().addDocumentListener(listener); + }); + } + + /** + * Tests whether or not values have been entered in all of the database + * settings text fields. + * + * @return True or false. + */ + @Messages({"EamDbSettingsDialog.validation.incompleteFields=Fill in all values for the selected database."}) + private boolean databaseFieldsArePopulated() { + boolean result = true; + switch (selectedPlatform) { + case POSTGRESQL: + result = !tbDbHostname.getText().trim().isEmpty() + && !tbDbPort.getText().trim().isEmpty() + && !tbDbName.getText().trim().isEmpty() + && !tbDbUsername.getText().trim().isEmpty() + && 0 < jpDbPassword.getPassword().length; + + break; + + case SQLITE: + result = !tfDatabasePath.getText().trim().isEmpty(); + break; + } + + if (!result) { + setGuidanceMessage(Bundle.EamDbSettingsDialog_validation_incompleteFields(), true); + } + + return result; + } + + /** + * Tests whether or not all of the settings components are populated. + * + * @return True or false. + */ + private boolean checkFields() { + return databaseFieldsArePopulated() + && databaseSettingsAreValid(); + } + + /** + * Tests whether or not the database settings are valid. + * + * @return True or false. + */ + private boolean databaseSettingsAreValid() { + boolean result = true; + StringBuilder guidanceText = new StringBuilder(); + + switch (selectedPlatform) { + case POSTGRESQL: + try { + dbSettingsPostgres.setHost(tbDbHostname.getText().trim()); + } catch (EamDbException ex) { + guidanceText.append(ex.getMessage()); + result = false; + } + + try { + dbSettingsPostgres.setPort(Integer.valueOf(tbDbPort.getText().trim())); + } catch (NumberFormatException | EamDbException ex) { + guidanceText.append(ex.getMessage()); + result = false; + } + + try { + dbSettingsPostgres.setDbName(tbDbName.getText().trim()); + } catch (EamDbException ex) { + guidanceText.append(ex.getMessage()); + result = false; + } + + try { + dbSettingsPostgres.setUserName(tbDbUsername.getText().trim()); + } catch (EamDbException ex) { + guidanceText.append(ex.getMessage()); + result = false; + } + + try { + dbSettingsPostgres.setPassword(new String(jpDbPassword.getPassword())); + } catch (EamDbException ex) { + guidanceText.append(ex.getMessage()); + result = false; + } + break; + case SQLITE: + try { + File databasePath = new File(tfDatabasePath.getText()); + dbSettingsSqlite.setDbName(databasePath.getName()); + dbSettingsSqlite.setDbDirectory(databasePath.getParent()); + } catch (EamDbException ex) { + guidanceText.append(ex.getMessage()); + result = false; + } + break; + } + + setGuidanceMessage(guidanceText.toString(), true); + return result; + } + + /** + * Validates that the form is filled out correctly for our usage. + * + * @return true if it's okay, false otherwise. + */ + private boolean valid() { + taSetupGuidance.setText(""); + return enableTestButton(checkFields()) + && enableCreateButton() + && enableOkButton(); + } + + /** + * Enable the "Test" button once all fields are valid. + * + * @return true + */ + @Messages({"EamDbSettingsDialog.validation.mustTest=Once you are statisfied with the database settings, click the Test button to test the database connection, settings, and schema.", + "EamDbSettingsDialog.validation.failedConnection=The connection to the database failed. Update the settings and try the Test again."}) + private boolean enableTestButton(boolean isValidInput) { + if (selectedPlatform != EamDbPlatformEnum.DISABLED && isValidInput) { + bnTest.setEnabled(true); + if (testingStatus == DatabaseTestResult.UNTESTED) { + setGuidanceMessage(Bundle.EamDbSettingsDialog_validation_mustTest(), false); + } else if (testingStatus == DatabaseTestResult.CONNECTION_FAILED) { + setGuidanceMessage(Bundle.EamDbSettingsDialog_validation_failedConnection(), true); + } + } else { + bnTest.setEnabled(false); + } + return true; + } + + /** + * Enable the "Create" button if the db is not created. + * + * @return true if db is created, else false + */ + @Messages({"EamDbSettingsDialog.validation.dbNotCreated=The database does not exist. Click the Create button to create and initialize the database."}) + private boolean enableCreateButton() { + if (testingStatus == DatabaseTestResult.SCHEMA_INVALID) { + bnCreateDb.setEnabled(true); + setGuidanceMessage(Bundle.EamDbSettingsDialog_validation_dbNotCreated(), false); + } else { + bnCreateDb.setEnabled(false); + } + return true; + } + + /** + * Enable the "OK" button if the db test passed. Disabled defaults to db test passed. + * + * @return true + */ + @Messages({"EamDbSettingsDialog.validation.finished=Click OK to save your database settings and return to the Options. Or select a differnt database type."}) + private boolean enableOkButton() { + if (testingStatus == DatabaseTestResult.TESTEDOK || selectedPlatform == EamDbPlatformEnum.DISABLED) { + bnOk.setEnabled(true); + setGuidanceMessage(Bundle.EamDbSettingsDialog_validation_finished(), false); + } else { + bnOk.setEnabled(false); + } + return true; + } + + /** + * Used to listen for changes in text boxes. It lets the panel know things + * have been updated and that validation needs to happen. + */ + private class TextBoxChangedListener implements DocumentListener { + + @Override + public void changedUpdate(DocumentEvent e) { + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + clearIcons(); + testingStatus = DatabaseTestResult.UNTESTED; + valid(); + } + + @Override + public void insertUpdate(DocumentEvent e) { + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + clearIcons(); + testingStatus = DatabaseTestResult.UNTESTED; + valid(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + clearIcons(); + testingStatus = DatabaseTestResult.UNTESTED; + valid(); + } + } + + private enum DatabaseTestResult { + UNTESTED, + CONNECTION_FAILED, + SCHEMA_INVALID, + TESTEDOK; + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton bnCancel; + private javax.swing.JButton bnCreateDb; + private javax.swing.JButton bnDatabasePathFileOpen; + private javax.swing.ButtonGroup bnGrpDatabasePlatforms; + private javax.swing.JButton bnOk; + private javax.swing.JButton bnTest; + private javax.swing.JFileChooser fcDatabasePath; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JPasswordField jpDbPassword; + private javax.swing.JLabel lbCreateIcon; + private javax.swing.JLabel lbDatabaseName; + private javax.swing.JLabel lbDatabasePath; + private javax.swing.JLabel lbHostName; + private javax.swing.JLabel lbPort; + private javax.swing.JLabel lbTestIcon; + private javax.swing.JLabel lbUserName; + private javax.swing.JLabel lbUserPassword; + private javax.swing.JPanel pnButtons; + private javax.swing.JPanel pnDatabaseConnectionSettings; + private javax.swing.JPanel pnPostgreSQLSettings; + private javax.swing.JPanel pnSQLiteSettings; + private javax.swing.JPanel pnSetupGuidance; + private javax.swing.JRadioButton rdioBnDisabled; + private javax.swing.JRadioButton rdioBnPostgreSQL; + private javax.swing.JRadioButton rdioBnSQLite; + private javax.swing.JTextArea taSetupGuidance; + private javax.swing.JTextField tbDbHostname; + private javax.swing.JTextField tbDbName; + private javax.swing.JTextField tbDbPort; + private javax.swing.JTextField tbDbUsername; + private javax.swing.JTextField tfDatabasePath; + // End of variables declaration//GEN-END:variables +} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamPostgresSettingsDialog.form b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamPostgresSettingsDialog.form deleted file mode 100644 index 31db936608..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamPostgresSettingsDialog.form +++ /dev/null @@ -1,246 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamPostgresSettingsDialog.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamPostgresSettingsDialog.java deleted file mode 100644 index 148551ffce..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamPostgresSettingsDialog.java +++ /dev/null @@ -1,545 +0,0 @@ -/* - * Enterprise Artifacts Manager - * - * Copyright 2015-2017 Basis Technology Corp. - * Contact: carrier sleuthkit 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.enterpriseartifactsmanager.optionspanel; - -import java.awt.Color; -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.Toolkit; -import java.util.ArrayList; -import java.util.Collection; -import javax.swing.ImageIcon; -import javax.swing.JFrame; -import javax.swing.JTextField; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import org.netbeans.spi.options.OptionsPanelController; -import org.openide.util.ImageUtilities; -import org.openide.util.NbBundle; -import org.openide.util.NbBundle.Messages; -import org.openide.windows.WindowManager; -import org.sleuthkit.autopsy.corecomponents.TextPrompt; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.PostgresEamDbSettings; - -/** - * Settings panel for the postgres-specific options - */ -public class EamPostgresSettingsDialog extends javax.swing.JDialog { - - private static final Logger LOGGER = Logger.getLogger(EamSqliteSettingsDialog.class.getName()); - private final ImageIcon goodIcon; - private final ImageIcon badIcon; - private final Collection textBoxes; - private final TextBoxChangedListener textBoxChangedListener; - - private final PostgresEamDbSettings dbSettings; - private Boolean hasChanged; - - /** - * Creates new form EnterpriseArtifactsManagerPostgresSettingsDialog - */ - @NbBundle.Messages({"EnterpriseArtifactsManagerPostgresSettingsDialog.postgresSettingsMessage.text=PostgreSQL Database Settings"}) - public EamPostgresSettingsDialog() { - super((JFrame) WindowManager.getDefault().getMainWindow(), - Bundle.EnterpriseArtifactsManagerPostgresSettingsDialog_postgresSettingsMessage_text(), - true); // NON-NLS - - textBoxes = new ArrayList<>(); - textBoxChangedListener = new TextBoxChangedListener(); - this.dbSettings = new PostgresEamDbSettings(); - goodIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/images/good.png", false)); // NON-NLS - badIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/images/bad.png", false)); // NON-NLS - - initComponents(); - customizeComponents(); - display(); - } - - /** - * Let calling object determine if this dialog made any changes. - * - * @return true or false - */ - public Boolean isChanged() { - return hasChanged; - } - - private void customizeComponents() { - hasChanged = false; - lbTestDatabaseWarning.setText(""); - setTextPrompts(); - setTextBoxStatusIcons(); - setTextBoxListeners(); - tbDbHostname.setText(dbSettings.getHost()); - tbDbPort.setText(Integer.toString(dbSettings.getPort())); - tbDbName.setText(dbSettings.getDbName()); - tbDbUsername.setText(dbSettings.getUserName()); - tbDbPassword.setText(dbSettings.getPassword()); - - enableTestDatabaseButton(false); - enableSaveButton(false); - this.valid(); - } - - private void display() { - Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); - setLocation((screenDimension.width - getSize().width) / 2, (screenDimension.height - getSize().height) / 2); - setVisible(true); - } - - /** - * Add text prompts to all of the text fields. - */ - @Messages({"EnterpriseArtifactsManagerPostgresSettingsDialog.textPrompt.hostnameOrIP=Hostname or IP Address", - "EnterpriseArtifactsManagerPostgresSettingsDialog.textPrompt.port=Port Number", - "EnterpriseArtifactsManagerPostgresSettingsDialog.textPrompt.dbName=Database Name", - "EnterpriseArtifactsManagerPostgresSettingsDialog.textPrompt.user=Database User", - "EnterpriseArtifactsManagerPostgresSettingsDialog.textPrompt.password=Database User's Password"}) - private void setTextPrompts() { - Collection textPrompts = new ArrayList<>(); - textPrompts.add(new TextPrompt(Bundle.EnterpriseArtifactsManagerPostgresSettingsDialog_textPrompt_hostnameOrIP(), tbDbHostname)); - textPrompts.add(new TextPrompt(Bundle.EnterpriseArtifactsManagerPostgresSettingsDialog_textPrompt_port(), tbDbPort)); - textPrompts.add(new TextPrompt(Bundle.EnterpriseArtifactsManagerPostgresSettingsDialog_textPrompt_dbName(), tbDbName)); - textPrompts.add(new TextPrompt(Bundle.EnterpriseArtifactsManagerPostgresSettingsDialog_textPrompt_user(), tbDbUsername)); - textPrompts.add(new TextPrompt(Bundle.EnterpriseArtifactsManagerPostgresSettingsDialog_textPrompt_password(), tbDbPassword)); - configureTextPrompts(textPrompts); - } - - /** - * Set each textbox with a "statusIcon" property enabling the - * DocumentListeners to know which icon to erase when changes are made - */ - private void setTextBoxStatusIcons() { - tbDbHostname.getDocument().putProperty("statusIcon", lbTestDatabase); // NON-NLS - tbDbPort.getDocument().putProperty("statusIcon", lbTestDatabase); // NON-NLS - tbDbName.getDocument().putProperty("statusIcon", lbTestDatabase); // NON-NLS - tbDbUsername.getDocument().putProperty("statusIcon", lbTestDatabase); // NON-NLS - tbDbPassword.getDocument().putProperty("statusIcon", lbTestDatabase); // NON-NLS - } - - /** - * Register for notifications when the text boxes get updated. - */ - private void setTextBoxListeners() { - textBoxes.add(tbDbHostname); - textBoxes.add(tbDbPort); - textBoxes.add(tbDbName); - textBoxes.add(tbDbUsername); - textBoxes.add(tbDbPassword); - addDocumentListeners(textBoxes, textBoxChangedListener); - } - - /** - * Sets the foreground color and transparency of a collection of text - * prompts. - * - * @param textPrompts The text prompts to configure. - */ - private static void configureTextPrompts(Collection textPrompts) { - float alpha = 0.9f; // Mostly opaque - for (TextPrompt textPrompt : textPrompts) { - textPrompt.setForeground(Color.LIGHT_GRAY); - textPrompt.changeAlpha(alpha); - } - } - - /** - * Adds a change listener to a collection of text fields. - * - * @param textFields The text fields. - * @param listener The change listener. - */ - private static void addDocumentListeners(Collection textFields, TextBoxChangedListener listener) { - textFields.forEach((textField) -> { - textField.getDocument().addDocumentListener(listener); - }); - } - - /** - * Tests whether or not values have been entered in all of the database - * settings text fields. - * - * @return True or false. - */ - private boolean databaseFieldsArePopulated() { - return !tbDbHostname.getText().trim().isEmpty() - && !tbDbPort.getText().trim().isEmpty() - && !tbDbName.getText().trim().isEmpty() - && !tbDbUsername.getText().trim().isEmpty() - && !tbDbPassword.getText().trim().isEmpty(); - } - - /** - * Tests whether or not all of the settings components are populated. - * - * @return True or false. - */ - @Messages({"EnterpriseArtifactsManagerPostgresSettingsDialog.validation.incompleteFields=Fill in all values"}) - private boolean checkFields() { - boolean result = true; - - boolean dbPopulated = databaseFieldsArePopulated(); - - if (!dbPopulated) { - // We don't even have everything filled out - result = false; - lbTestDatabaseWarning.setText(Bundle.EnterpriseArtifactsManagerPostgresSettingsDialog_validation_incompleteFields()); - } - return result; - } - - /** - * Tests whether or not the database settings are valid. - * - * @return True or false. - */ - @Messages({"EnterpriseArtifactsManagerPostgresSettingsDialog.validation.invalidHost=Invalid database hostname.", - "EnterpriseArtifactsManagerPostgresSettingsDialog.validation.invalidPort=Invalid database port number.", - "EnterpriseArtifactsManagerPostgresSettingsDialog.validation.invalidDbName=Invalid database name.", - "EnterpriseArtifactsManagerPostgresSettingsDialog.validation.invalidDbUser=Invalid database username.", - "EnterpriseArtifactsManagerPostgresSettingsDialog.validation.invalidDbPassword=Invalid database password.",}) - private boolean databaseSettingsAreValid() { - - try { - dbSettings.setHost(tbDbHostname.getText().trim()); - } catch (EamDbException ex) { - lbTestDatabaseWarning.setText(Bundle.EnterpriseArtifactsManagerPostgresSettingsDialog_validation_invalidHost()); - return false; - } - - try { - dbSettings.setPort(Integer.valueOf(tbDbPort.getText().trim())); - } catch (NumberFormatException | EamDbException ex) { - lbTestDatabaseWarning.setText(Bundle.EnterpriseArtifactsManagerPostgresSettingsDialog_validation_invalidPort()); - return false; - } - - try { - dbSettings.setDbName(tbDbName.getText().trim()); - } catch (EamDbException ex) { - lbTestDatabaseWarning.setText(Bundle.EnterpriseArtifactsManagerPostgresSettingsDialog_validation_invalidDbName()); - return false; - } - - try { - dbSettings.setUserName(tbDbUsername.getText().trim()); - } catch (EamDbException ex) { - lbTestDatabaseWarning.setText(Bundle.EnterpriseArtifactsManagerPostgresSettingsDialog_validation_invalidDbUser()); - return false; - } - - try { - dbSettings.setPassword(tbDbPassword.getText().trim()); - } catch (EamDbException ex) { - lbTestDatabaseWarning.setText(Bundle.EnterpriseArtifactsManagerPostgresSettingsDialog_validation_invalidDbPassword()); - return false; - } - - return true; - } - - /** - * Validates that the form is filled out correctly for our usage. - * - * @return true if it's okay, false otherwise. - */ - public boolean valid() { - lbTestDatabaseWarning.setText(""); - - return checkFields() - && enableTestDatabaseButton(databaseSettingsAreValid()) - && enableSaveButton(databaseSettingsAreValid()); - } - - /** - * Enables the "Test Connection" button to test the database settings. - * - * @param enable - * - * @return True or False - */ - private boolean enableTestDatabaseButton(Boolean enable) { - bnTestConnection.setEnabled(enable); - return enable; - } - - /** - * Enables the "Save" button to save the database settings. - * - * @param enable - * - * @return True or False - */ - private boolean enableSaveButton(Boolean enable) { - bnSave.setEnabled(enable); - return enable; - } - - /** - * Used to listen for changes in text boxes. It lets the panel know things - * have been updated and that validation needs to happen. - */ - private class TextBoxChangedListener implements DocumentListener { - - @Override - public void changedUpdate(DocumentEvent e) { - Object statusIcon = e.getDocument().getProperty("statusIcon"); // NON-NLS - if (statusIcon != null) { - ((javax.swing.JLabel) statusIcon).setIcon(null); - } - firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - valid(); - } - - @Override - public void insertUpdate(DocumentEvent e) { - Object statusIcon = e.getDocument().getProperty("statusIcon"); // NON-NLS - if (statusIcon != null) { - ((javax.swing.JLabel) statusIcon).setIcon(null); - } - firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - valid(); - } - - @Override - public void removeUpdate(DocumentEvent e) { - Object statusIcon = e.getDocument().getProperty("statusIcon"); // NON-NLS - if (statusIcon != null) { - ((javax.swing.JLabel) statusIcon).setIcon(null); - } - firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - valid(); - } - } - - /** - * 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") - // //GEN-BEGIN:initComponents - private void initComponents() { - - pnOuter = new javax.swing.JPanel(); - jScrollPane = new javax.swing.JScrollPane(); - pnContent = new javax.swing.JPanel(); - lbHostName = new javax.swing.JLabel(); - lbPort = new javax.swing.JLabel(); - lbUserName = new javax.swing.JLabel(); - lbUserPassword = new javax.swing.JLabel(); - lbDatabaseName = new javax.swing.JLabel(); - tbDbHostname = new javax.swing.JTextField(); - tbDbPort = new javax.swing.JTextField(); - tbDbName = new javax.swing.JTextField(); - tbDbUsername = new javax.swing.JTextField(); - tbDbPassword = new javax.swing.JTextField(); - bnTestConnection = new javax.swing.JButton(); - bnSave = new javax.swing.JButton(); - bnCancel = new javax.swing.JButton(); - lbTestDatabaseWarning = new javax.swing.JLabel(); - lbTestDatabase = new javax.swing.JLabel(); - - setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - - org.openide.awt.Mnemonics.setLocalizedText(lbHostName, org.openide.util.NbBundle.getMessage(EamPostgresSettingsDialog.class, "EamPostgresSettingsDialog.lbHostName.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(lbPort, org.openide.util.NbBundle.getMessage(EamPostgresSettingsDialog.class, "EamPostgresSettingsDialog.lbPort.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(lbUserName, org.openide.util.NbBundle.getMessage(EamPostgresSettingsDialog.class, "EamPostgresSettingsDialog.lbUserName.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(lbUserPassword, org.openide.util.NbBundle.getMessage(EamPostgresSettingsDialog.class, "EamPostgresSettingsDialog.lbUserPassword.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(lbDatabaseName, org.openide.util.NbBundle.getMessage(EamPostgresSettingsDialog.class, "EamPostgresSettingsDialog.lbDatabaseName.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(bnTestConnection, org.openide.util.NbBundle.getMessage(EamPostgresSettingsDialog.class, "EamPostgresSettingsDialog.bnTestConnection.text")); // NOI18N - bnTestConnection.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - bnTestConnectionActionPerformed(evt); - } - }); - - org.openide.awt.Mnemonics.setLocalizedText(bnSave, org.openide.util.NbBundle.getMessage(EamPostgresSettingsDialog.class, "EamPostgresSettingsDialog.bnSave.text")); // NOI18N - bnSave.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - bnSaveActionPerformed(evt); - } - }); - - org.openide.awt.Mnemonics.setLocalizedText(bnCancel, org.openide.util.NbBundle.getMessage(EamPostgresSettingsDialog.class, "EamPostgresSettingsDialog.bnCancel.text")); // NOI18N - bnCancel.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - bnCancelActionPerformed(evt); - } - }); - - lbTestDatabaseWarning.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N - lbTestDatabaseWarning.setForeground(new java.awt.Color(255, 0, 0)); - - javax.swing.GroupLayout pnContentLayout = new javax.swing.GroupLayout(pnContent); - pnContent.setLayout(pnContentLayout); - pnContentLayout.setHorizontalGroup( - pnContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnContentLayout.createSequentialGroup() - .addContainerGap() - .addGroup(pnContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnContentLayout.createSequentialGroup() - .addComponent(bnTestConnection) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(lbTestDatabase, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(153, 153, 153) - .addComponent(bnSave) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(bnCancel)) - .addGroup(pnContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) - .addComponent(lbTestDatabaseWarning, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, pnContentLayout.createSequentialGroup() - .addGroup(pnContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(lbHostName) - .addComponent(lbPort) - .addComponent(lbDatabaseName) - .addComponent(lbUserName) - .addComponent(lbUserPassword)) - .addGap(18, 18, 18) - .addGroup(pnContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(tbDbPassword, javax.swing.GroupLayout.DEFAULT_SIZE, 322, Short.MAX_VALUE) - .addComponent(tbDbUsername) - .addComponent(tbDbName) - .addComponent(tbDbHostname) - .addComponent(tbDbPort, javax.swing.GroupLayout.PREFERRED_SIZE, 67, javax.swing.GroupLayout.PREFERRED_SIZE))))) - .addGap(0, 11, Short.MAX_VALUE)) - ); - pnContentLayout.setVerticalGroup( - pnContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnContentLayout.createSequentialGroup() - .addContainerGap() - .addGroup(pnContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(tbDbHostname, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lbHostName, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(tbDbPort) - .addComponent(lbPort, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(tbDbName) - .addComponent(lbDatabaseName, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(tbDbUsername) - .addComponent(lbUserName, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lbUserPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(tbDbPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGap(37, 37, 37) - .addComponent(lbTestDatabaseWarning, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(pnContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(bnTestConnection) - .addComponent(bnSave) - .addComponent(bnCancel) - .addComponent(lbTestDatabase, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGap(0, 0, Short.MAX_VALUE)) - ); - - jScrollPane.setViewportView(pnContent); - - javax.swing.GroupLayout pnOuterLayout = new javax.swing.GroupLayout(pnOuter); - pnOuter.setLayout(pnOuterLayout); - pnOuterLayout.setHorizontalGroup( - pnOuterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 448, Short.MAX_VALUE) - .addGroup(pnOuterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnOuterLayout.createSequentialGroup() - .addComponent(jScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 448, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, Short.MAX_VALUE))) - ); - pnOuterLayout.setVerticalGroup( - pnOuterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 249, Short.MAX_VALUE) - .addGroup(pnOuterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnOuterLayout.createSequentialGroup() - .addComponent(jScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 249, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, Short.MAX_VALUE))) - ); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); - getContentPane().setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(pnOuter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(pnOuter, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - ); - - pack(); - }// //GEN-END:initComponents - - private void bnTestConnectionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnTestConnectionActionPerformed - lbTestDatabase.setIcon(null); - lbTestDatabase.setText(""); - setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - - if (dbSettings.testSettings()) { - lbTestDatabase.setIcon(goodIcon); - } else { - lbTestDatabase.setIcon(badIcon); - } - - setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - - }//GEN-LAST:event_bnTestConnectionActionPerformed - - private void bnSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnSaveActionPerformed - hasChanged = true; - dbSettings.setEnabled(true); - dbSettings.saveSettings(); - dispose(); - }//GEN-LAST:event_bnSaveActionPerformed - - private void bnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnCancelActionPerformed - dispose(); - }//GEN-LAST:event_bnCancelActionPerformed - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton bnCancel; - private javax.swing.JButton bnSave; - private javax.swing.JButton bnTestConnection; - private javax.swing.JScrollPane jScrollPane; - private javax.swing.JLabel lbDatabaseName; - private javax.swing.JLabel lbHostName; - private javax.swing.JLabel lbPort; - private javax.swing.JLabel lbTestDatabase; - private javax.swing.JLabel lbTestDatabaseWarning; - private javax.swing.JLabel lbUserName; - private javax.swing.JLabel lbUserPassword; - private javax.swing.JPanel pnContent; - private javax.swing.JPanel pnOuter; - private javax.swing.JTextField tbDbHostname; - private javax.swing.JTextField tbDbName; - private javax.swing.JTextField tbDbPassword; - private javax.swing.JTextField tbDbPort; - private javax.swing.JTextField tbDbUsername; - // End of variables declaration//GEN-END:variables -} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamSqliteSettingsDialog.form b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamSqliteSettingsDialog.form deleted file mode 100644 index 9ab466696d..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamSqliteSettingsDialog.form +++ /dev/null @@ -1,218 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamSqliteSettingsDialog.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamSqliteSettingsDialog.java deleted file mode 100644 index e46288dd21..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamSqliteSettingsDialog.java +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Enterprise Artifacts Manager - * - * Copyright 2015-2017 Basis Technology Corp. - * Contact: carrier sleuthkit 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.enterpriseartifactsmanager.optionspanel; - -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.Toolkit; -import java.io.File; -import java.io.IOException; -import java.util.logging.Level; -import javax.swing.ImageIcon; -import javax.swing.JFileChooser; -import javax.swing.JFrame; -import javax.swing.JOptionPane; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import javax.swing.filechooser.FileNameExtensionFilter; -import org.netbeans.spi.options.OptionsPanelController; -import org.openide.util.ImageUtilities; -import org.openide.util.NbBundle.Messages; -import org.openide.windows.WindowManager; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.SqliteEamDbSettings; - -/** - * Settings panel for the sqlite-specific options - */ -public class EamSqliteSettingsDialog extends javax.swing.JDialog { - - private static final Logger LOGGER = Logger.getLogger(EamSqliteSettingsDialog.class.getName()); - private final ImageIcon goodIcon; - private final ImageIcon badIcon; - private final TextBoxChangedListener textBoxChangedListener; - - private final SqliteEamDbSettings dbSettings; - private Boolean hasChanged; - - /** - * Creates new form EnterpriseArtifactsManagerSQLiteSettingsDialog - */ - @Messages({"EnterpriseArtifactsManagerSQLiteSettingsDialog.sqliteSettingsMessage.text=SQLite Database Settings"}) - public EamSqliteSettingsDialog() { - super((JFrame) WindowManager.getDefault().getMainWindow(), - Bundle.EnterpriseArtifactsManagerSQLiteSettingsDialog_sqliteSettingsMessage_text(), - true); // NON-NLS - - this.dbSettings = new SqliteEamDbSettings(); - goodIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/images/good.png", false)); // NON-NLS - badIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/images/bad.png", false)); // NON-NLS - textBoxChangedListener = new TextBoxChangedListener(); - - initComponents(); - customizeComponents(); - valid(); - display(); - } - - /** - * Let calling object determine if this dialog made any changes. - * - * @return true or false - */ - public Boolean isChanged() { - return hasChanged; - } - - private void customizeComponents() { - customizeFileChooser(); - tfDatabasePath.setText(dbSettings.getFileNameWithPath()); - lbTestDatabaseWarning.setText(""); - hasChanged = false; - tfDatabasePath.getDocument().addDocumentListener(textBoxChangedListener); - bnSave.setEnabled(false); - bnTestDatabase.setEnabled(false); - } - - @Messages({"EnterpriseArtifactsManagerSQLiteSettingsDialog.fileNameExtFilter.text=SQLite Database File"}) - private void customizeFileChooser() { - fcDatabasePath.setDragEnabled(false); - fcDatabasePath.setFileSelectionMode(JFileChooser.FILES_ONLY); - String[] EXTENSION = new String[]{"db"}; //NON-NLS - FileNameExtensionFilter filter = new FileNameExtensionFilter(Bundle.EnterpriseArtifactsManagerSQLiteSettingsDialog_fileNameExtFilter_text(), EXTENSION); // NON-NLS - fcDatabasePath.setFileFilter(filter); - fcDatabasePath.setMultiSelectionEnabled(false); - } - - private void display() { - Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); - setLocation((screenDimension.width - getSize().width) / 2, (screenDimension.height - getSize().height) / 2); - setVisible(true); - } - - /** - * Used to listen for changes in text boxes. It lets the panel know things - * have been updated and that validation needs to happen. - */ - private class TextBoxChangedListener implements DocumentListener { - - @Override - public void changedUpdate(DocumentEvent e) { - firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - valid(); - } - - @Override - public void insertUpdate(DocumentEvent e) { - firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - valid(); - } - - @Override - public void removeUpdate(DocumentEvent e) { - firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - valid(); - } - } - - private boolean valid() { - boolean result = false; - if (tfDatabasePath.getText().trim().isEmpty()) { - bnSave.setEnabled(false); - bnTestDatabase.setEnabled(false); - } else { - storeDbNameAndDirectory(); - bnSave.setEnabled(true); - bnTestDatabase.setEnabled(true); - result = true; - } - return result; - } - - /** - * Get the db file name and directory path from the file chooser and store - * in dbSettings. - */ - @Messages({"EnterpriseArtifactsManagerSQLiteSettingsDialog.storeDbNameAndDirectory.failedToSetDbNamePathMsg=Database filename or directory path is missing. Try again."}) - private void storeDbNameAndDirectory() { - File databasePath = new File(tfDatabasePath.getText()); - try { - dbSettings.setDbName(databasePath.getName()); - dbSettings.setDbDirectory(databasePath.getParent()); - } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Failed to set database name or directory path.", ex); // NON-NLS - JOptionPane.showMessageDialog(this, Bundle.EnterpriseArtifactsManagerSQLiteSettingsDialog_storeDbNameAndDirectory_failedToSetDbNamePathMsg()); - } - } - - /** - * 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") - // //GEN-BEGIN:initComponents - private void initComponents() { - - fcDatabasePath = new javax.swing.JFileChooser(); - pnOuter = new javax.swing.JPanel(); - jScrollPane = new javax.swing.JScrollPane(); - pnContent = new javax.swing.JPanel(); - lbDatabasePath = new javax.swing.JLabel(); - tfDatabasePath = new javax.swing.JTextField(); - bnDatabasePathFileOpen = new javax.swing.JButton(); - lbTestDatabaseWarning = new javax.swing.JLabel(); - bnTestDatabase = new javax.swing.JButton(); - lbTestDatabase = new javax.swing.JLabel(); - bnCancel = new javax.swing.JButton(); - bnSave = new javax.swing.JButton(); - - setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - - org.openide.awt.Mnemonics.setLocalizedText(lbDatabasePath, org.openide.util.NbBundle.getMessage(EamSqliteSettingsDialog.class, "EamSqliteSettingsDialog.lbDatabasePath.text")); // NOI18N - - tfDatabasePath.setText(org.openide.util.NbBundle.getMessage(EamSqliteSettingsDialog.class, "EamSqliteSettingsDialog.tfDatabasePath.text")); // NOI18N - tfDatabasePath.setToolTipText(org.openide.util.NbBundle.getMessage(EamSqliteSettingsDialog.class, "EamSqliteSettingsDialog.tfDatabasePath.toolTipText")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(bnDatabasePathFileOpen, org.openide.util.NbBundle.getMessage(EamSqliteSettingsDialog.class, "EamSqliteSettingsDialog.bnDatabasePathFileOpen.text")); // NOI18N - bnDatabasePathFileOpen.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - bnDatabasePathFileOpenActionPerformed(evt); - } - }); - - lbTestDatabaseWarning.setForeground(new java.awt.Color(255, 51, 51)); - org.openide.awt.Mnemonics.setLocalizedText(lbTestDatabaseWarning, org.openide.util.NbBundle.getMessage(EamSqliteSettingsDialog.class, "EamSqliteSettingsDialog.lbTestDatabaseWarning.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(bnTestDatabase, org.openide.util.NbBundle.getMessage(EamSqliteSettingsDialog.class, "EamSqliteSettingsDialog.bnTestDatabase.text")); // NOI18N - bnTestDatabase.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - bnTestDatabaseActionPerformed(evt); - } - }); - - org.openide.awt.Mnemonics.setLocalizedText(lbTestDatabase, org.openide.util.NbBundle.getMessage(EamSqliteSettingsDialog.class, "EamSqliteSettingsDialog.lbTestDatabase.text")); // NOI18N - lbTestDatabase.setName(""); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(bnCancel, org.openide.util.NbBundle.getMessage(EamSqliteSettingsDialog.class, "EamSqliteSettingsDialog.bnCancel.text")); // NOI18N - bnCancel.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - bnCancelActionPerformed(evt); - } - }); - - org.openide.awt.Mnemonics.setLocalizedText(bnSave, org.openide.util.NbBundle.getMessage(EamSqliteSettingsDialog.class, "EamSqliteSettingsDialog.bnSave.text")); // NOI18N - bnSave.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - bnSaveActionPerformed(evt); - } - }); - - javax.swing.GroupLayout pnContentLayout = new javax.swing.GroupLayout(pnContent); - pnContent.setLayout(pnContentLayout); - pnContentLayout.setHorizontalGroup( - pnContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnContentLayout.createSequentialGroup() - .addContainerGap() - .addGroup(pnContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnContentLayout.createSequentialGroup() - .addGroup(pnContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) - .addComponent(lbTestDatabaseWarning, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(pnContentLayout.createSequentialGroup() - .addComponent(lbDatabasePath) - .addGap(18, 18, 18) - .addComponent(tfDatabasePath, javax.swing.GroupLayout.PREFERRED_SIZE, 343, javax.swing.GroupLayout.PREFERRED_SIZE))) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 57, Short.MAX_VALUE) - .addComponent(bnDatabasePathFileOpen) - .addGap(24, 24, 24)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnContentLayout.createSequentialGroup() - .addComponent(bnTestDatabase) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(lbTestDatabase, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(bnSave) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(bnCancel) - .addContainerGap()))) - ); - pnContentLayout.setVerticalGroup( - pnContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnContentLayout.createSequentialGroup() - .addContainerGap() - .addGroup(pnContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lbDatabasePath, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(tfDatabasePath, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(bnDatabasePathFileOpen)) - .addGap(18, 18, 18) - .addComponent(lbTestDatabaseWarning, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGroup(pnContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnContentLayout.createSequentialGroup() - .addGap(19, 19, 19) - .addGroup(pnContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(bnCancel) - .addComponent(bnSave))) - .addGroup(pnContentLayout.createSequentialGroup() - .addGap(18, 18, 18) - .addGroup(pnContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(lbTestDatabase, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(bnTestDatabase)))) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - ); - - jScrollPane.setViewportView(pnContent); - - javax.swing.GroupLayout pnOuterLayout = new javax.swing.GroupLayout(pnOuter); - pnOuter.setLayout(pnOuterLayout); - pnOuterLayout.setHorizontalGroup( - pnOuterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane) - ); - pnOuterLayout.setVerticalGroup( - pnOuterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - ); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); - getContentPane().setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 603, Short.MAX_VALUE) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(pnOuter, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 129, Short.MAX_VALUE) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(pnOuter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, Short.MAX_VALUE))) - ); - - pack(); - }// //GEN-END:initComponents - - @Messages({"EnterpriseArtifactsManagerSQLiteSettingsDialog.chooserPath.failedToGetDbPathMsg=Selected database path is invalid. Try again."}) - private void bnDatabasePathFileOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnDatabasePathFileOpenActionPerformed - if (fcDatabasePath.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { - File databaseFile = fcDatabasePath.getSelectedFile(); - try { - tfDatabasePath.setText(databaseFile.getCanonicalPath()); - valid(); - - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, "Failed to get path of selected database file", ex); // NON-NLS - JOptionPane.showMessageDialog(this, Bundle.EnterpriseArtifactsManagerSQLiteSettingsDialog_chooserPath_failedToGetDbPathMsg()); - } - } - }//GEN-LAST:event_bnDatabasePathFileOpenActionPerformed - - private void bnTestDatabaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnTestDatabaseActionPerformed - lbTestDatabase.setIcon(null); - lbTestDatabaseWarning.setText(""); - setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - - if (dbSettings.testSettings()) { - lbTestDatabase.setIcon(goodIcon); - } else { - lbTestDatabase.setIcon(badIcon); - } - - setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - }//GEN-LAST:event_bnTestDatabaseActionPerformed - - private void bnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnCancelActionPerformed - dispose(); - }//GEN-LAST:event_bnCancelActionPerformed - - private void bnSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnSaveActionPerformed - hasChanged = true; - dbSettings.setEnabled(true); - dbSettings.saveSettings(); - dispose(); - }//GEN-LAST:event_bnSaveActionPerformed - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton bnCancel; - private javax.swing.JButton bnDatabasePathFileOpen; - private javax.swing.JButton bnSave; - private javax.swing.JButton bnTestDatabase; - private javax.swing.JFileChooser fcDatabasePath; - private javax.swing.JScrollPane jScrollPane; - private javax.swing.JLabel lbDatabasePath; - private javax.swing.JLabel lbTestDatabase; - private javax.swing.JLabel lbTestDatabaseWarning; - private javax.swing.JPanel pnContent; - private javax.swing.JPanel pnOuter; - private javax.swing.JTextField tfDatabasePath; - // End of variables declaration//GEN-END:variables -} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/GlobalSettingsPanel.form b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/GlobalSettingsPanel.form index 29154fc5ea..02edd5748e 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/GlobalSettingsPanel.form +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/GlobalSettingsPanel.form @@ -19,259 +19,226 @@ - + + + + + + + + + - - - + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/GlobalSettingsPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/GlobalSettingsPanel.java index b0a2624224..ca37fc5f03 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/GlobalSettingsPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/GlobalSettingsPanel.java @@ -21,8 +21,6 @@ package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.optionspan import org.sleuthkit.autopsy.coreutils.Logger; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import javax.swing.JComboBox; -import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import org.netbeans.spi.options.OptionsPanelController; import org.openide.util.NbBundle.Messages; @@ -32,7 +30,8 @@ import org.sleuthkit.autopsy.events.AutopsyEvent; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel; import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbPlatformEnum; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb; +import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.PostgresEamDbSettings; +import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.SqliteEamDbSettings; /** * Main settings panel for the enterprise artifacts manager @@ -44,10 +43,6 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i private final IngestJobEventPropertyChangeListener ingestJobEventListener; - private boolean dbConfigured; - private boolean initiallyEnabled; - private boolean comboboxSelectDatabaseTypeActionListenerActive; - /** * Creates new form EnterpriseArtifactsManagerOptionsPanel */ @@ -62,12 +57,6 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i @Messages({"GlobalSettingsPanel.title=Global Enterprise Artifacts Manager Settings"}) private void customizeComponents() { setName(Bundle.GlobalSettingsPanel_title()); - comboboxSelectDatabaseTypeActionListenerActive = false; // don't fire action listener while loading combobox content - comboboxSelectDatabaseType.removeAllItems(); - for (EamDbPlatformEnum p : EamDbPlatformEnum.values()) { - comboboxSelectDatabaseType.addItem(p.toString()); - } - comboboxSelectDatabaseTypeActionListenerActive = true; } private void addIngestJobEventsListener() { @@ -84,22 +73,77 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i // //GEN-BEGIN:initComponents private void initComponents() { - jScrollPane = new javax.swing.JScrollPane(); - pnOverallPanel = new javax.swing.JPanel(); - pnSettings = new javax.swing.JPanel(); + pnDatabaseConfiguration = new javax.swing.JPanel(); + lbDbPlatformTypeLabel = new javax.swing.JLabel(); + lbDbNameLabel = new javax.swing.JLabel(); + lbDbLocationLabel = new javax.swing.JLabel(); + bnDbConfigure = new javax.swing.JButton(); + lbDbPlatformValue = new javax.swing.JLabel(); + lbDbNameValue = new javax.swing.JLabel(); + lbDbLocationValue = new javax.swing.JLabel(); + pnDatabaseContentButtons = new javax.swing.JPanel(); bnImportDatabase = new javax.swing.JButton(); - pnDatabaseConnectionSettings = new javax.swing.JPanel(); - comboboxSelectDatabaseType = new javax.swing.JComboBox<>(); - lbDatabasePlatform = new javax.swing.JLabel(); - bnConfigureDatabaseSettings = new javax.swing.JButton(); - tbOops = new javax.swing.JTextField(); bnManageTags = new javax.swing.JButton(); bnManageTypes = new javax.swing.JButton(); - cbEnableEnterpriseArtifactsManager = new javax.swing.JCheckBox(); + tbOops = new javax.swing.JTextField(); setName(""); // NOI18N - jScrollPane.setBorder(null); + pnDatabaseConfiguration.setBorder(javax.swing.BorderFactory.createTitledBorder(null, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.pnDatabaseConfiguration.title"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 0, 12))); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(lbDbPlatformTypeLabel, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.lbDbPlatformTypeLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(lbDbNameLabel, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.lbDbNameLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(lbDbLocationLabel, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.lbDbLocationLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(bnDbConfigure, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnDbConfigure.text")); // NOI18N + bnDbConfigure.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + bnDbConfigureActionPerformed(evt); + } + }); + + javax.swing.GroupLayout pnDatabaseConfigurationLayout = new javax.swing.GroupLayout(pnDatabaseConfiguration); + pnDatabaseConfiguration.setLayout(pnDatabaseConfigurationLayout); + pnDatabaseConfigurationLayout.setHorizontalGroup( + pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnDatabaseConfigurationLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnDatabaseConfigurationLayout.createSequentialGroup() + .addGroup(pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(lbDbPlatformTypeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(lbDbNameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(lbDbLocationLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 57, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lbDbPlatformValue, javax.swing.GroupLayout.PREFERRED_SIZE, 711, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lbDbNameValue, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 711, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(lbDbLocationValue, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 711, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addComponent(bnDbConfigure)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + pnDatabaseConfigurationLayout.setVerticalGroup( + pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnDatabaseConfigurationLayout.createSequentialGroup() + .addGap(7, 7, 7) + .addGroup(pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(lbDbPlatformTypeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(lbDbPlatformValue, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(lbDbNameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(lbDbNameValue, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(lbDbLocationLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(lbDbLocationValue, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 11, Short.MAX_VALUE) + .addComponent(bnDbConfigure) + .addContainerGap()) + ); bnImportDatabase.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/experimental/images/import16.png"))); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnImportDatabase, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnImportDatabase.label")); // NOI18N @@ -110,54 +154,6 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i } }); - pnDatabaseConnectionSettings.setBorder(javax.swing.BorderFactory.createTitledBorder(null, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.lbDatabaseSettings.text"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 0, 12))); // NOI18N - pnDatabaseConnectionSettings.setName(""); // NOI18N - - comboboxSelectDatabaseType.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "test 1", "test 2" })); - comboboxSelectDatabaseType.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - comboboxSelectDatabaseTypeActionPerformed(evt); - } - }); - - org.openide.awt.Mnemonics.setLocalizedText(lbDatabasePlatform, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.lbDatabasePlatform.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(bnConfigureDatabaseSettings, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnConfigureDatabaseSettings.text")); // NOI18N - bnConfigureDatabaseSettings.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - bnConfigureDatabaseSettingsActionPerformed(evt); - } - }); - - javax.swing.GroupLayout pnDatabaseConnectionSettingsLayout = new javax.swing.GroupLayout(pnDatabaseConnectionSettings); - pnDatabaseConnectionSettings.setLayout(pnDatabaseConnectionSettingsLayout); - pnDatabaseConnectionSettingsLayout.setHorizontalGroup( - pnDatabaseConnectionSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnDatabaseConnectionSettingsLayout.createSequentialGroup() - .addContainerGap() - .addComponent(lbDatabasePlatform) - .addGap(18, 18, 18) - .addComponent(comboboxSelectDatabaseType, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(bnConfigureDatabaseSettings) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - ); - pnDatabaseConnectionSettingsLayout.setVerticalGroup( - pnDatabaseConnectionSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnDatabaseConnectionSettingsLayout.createSequentialGroup() - .addGap(3, 3, 3) - .addGroup(pnDatabaseConnectionSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lbDatabasePlatform, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(comboboxSelectDatabaseType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(bnConfigureDatabaseSettings))) - ); - - 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.setText(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.tbOops.text")); // NOI18N - tbOops.setBorder(null); - org.openide.awt.Mnemonics.setLocalizedText(bnManageTags, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnManageTags.text")); // NOI18N bnManageTags.setToolTipText(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnManageTags.toolTipText")); // NOI18N bnManageTags.setActionCommand(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnManageTags.actionCommand")); // NOI18N @@ -174,229 +170,130 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i } }); - javax.swing.GroupLayout pnSettingsLayout = new javax.swing.GroupLayout(pnSettings); - pnSettings.setLayout(pnSettingsLayout); - pnSettingsLayout.setHorizontalGroup( - pnSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnSettingsLayout.createSequentialGroup() + javax.swing.GroupLayout pnDatabaseContentButtonsLayout = new javax.swing.GroupLayout(pnDatabaseContentButtons); + pnDatabaseContentButtons.setLayout(pnDatabaseContentButtonsLayout); + pnDatabaseContentButtonsLayout.setHorizontalGroup( + pnDatabaseContentButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnDatabaseContentButtonsLayout.createSequentialGroup() .addContainerGap() - .addGroup(pnSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(tbOops) - .addGroup(pnSettingsLayout.createSequentialGroup() - .addGroup(pnSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(pnDatabaseConnectionSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGroup(pnSettingsLayout.createSequentialGroup() - .addComponent(bnImportDatabase) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(bnManageTags) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(bnManageTypes))) - .addGap(0, 188, Short.MAX_VALUE))) - .addContainerGap()) - ); - pnSettingsLayout.setVerticalGroup( - pnSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnSettingsLayout.createSequentialGroup() - .addGap(8, 8, 8) - .addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(bnImportDatabase) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pnDatabaseConnectionSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 33, Short.MAX_VALUE) - .addGroup(pnSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(bnManageTags) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(bnManageTypes) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + pnDatabaseContentButtonsLayout.setVerticalGroup( + pnDatabaseContentButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnDatabaseContentButtonsLayout.createSequentialGroup() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(pnDatabaseContentButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(bnImportDatabase) .addComponent(bnManageTags, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(bnManageTypes, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(34, 34, 34)) ); - cbEnableEnterpriseArtifactsManager.setFont(cbEnableEnterpriseArtifactsManager.getFont().deriveFont(cbEnableEnterpriseArtifactsManager.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); - org.openide.awt.Mnemonics.setLocalizedText(cbEnableEnterpriseArtifactsManager, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.cbEnableEnterpriseArtifactsManager.text")); // NOI18N - cbEnableEnterpriseArtifactsManager.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - cbEnableEnterpriseArtifactsManagerItemStateChanged(evt); - } - }); - - javax.swing.GroupLayout pnOverallPanelLayout = new javax.swing.GroupLayout(pnOverallPanel); - pnOverallPanel.setLayout(pnOverallPanelLayout); - pnOverallPanelLayout.setHorizontalGroup( - pnOverallPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnOverallPanelLayout.createSequentialGroup() - .addContainerGap() - .addGroup(pnOverallPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnOverallPanelLayout.createSequentialGroup() - .addComponent(cbEnableEnterpriseArtifactsManager, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, Short.MAX_VALUE)) - .addComponent(pnSettings, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) - ); - pnOverallPanelLayout.setVerticalGroup( - pnOverallPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnOverallPanelLayout.createSequentialGroup() - .addComponent(cbEnableEnterpriseArtifactsManager) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pnSettings, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - ); - - jScrollPane.setViewportView(pnOverallPanel); + tbOops.setEditable(false); + tbOops.setFont(tbOops.getFont().deriveFont(tbOops.getFont().getStyle() | java.awt.Font.BOLD, 12)); + tbOops.setText(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.tbOops.text")); // NOI18N + tbOops.setBorder(null); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(pnDatabaseContentButtons, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(tbOops, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(pnDatabaseConfiguration, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(jScrollPane) - .addGap(2, 2, 2)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addComponent(pnDatabaseConfiguration, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pnDatabaseContentButtons, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 18, Short.MAX_VALUE)) ); }// //GEN-END:initComponents - private void cbEnableEnterpriseArtifactsManagerItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cbEnableEnterpriseArtifactsManagerItemStateChanged - tbOops.setText(""); - if (!cbEnableEnterpriseArtifactsManager.isSelected()) { - enableAllSubComponents(false); - firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - } else { - enableDatabaseSubComponents(true); - validateDatabaseSettings(); - } - }//GEN-LAST:event_cbEnableEnterpriseArtifactsManagerItemStateChanged - private void bnImportDatabaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnImportDatabaseActionPerformed ImportHashDatabaseDialog dialog = new ImportHashDatabaseDialog(); firePropertyChange(OptionsPanelController.PROP_VALID, null, null); }//GEN-LAST:event_bnImportDatabaseActionPerformed - /** - * When the "Configure" button is clicked, open the proper dialog. - * - * @param evt Button event - */ - @Messages({"GlobalSettingsPanel.configureButton.errorLabel=You must select a valid platform in the drop down box.", - "GlobalSettingsPanel.configureButton.errorTitle=Invalid platform selection."}) - private void bnConfigureDatabaseSettingsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnConfigureDatabaseSettingsActionPerformed - EamDbPlatformEnum selectedPlatform = EamDbPlatformEnum.getSelectedPlatform(); - Boolean dbConfigChanged = false; - - switch (selectedPlatform) { - case SQLITE: - EamSqliteSettingsDialog dialogS = new EamSqliteSettingsDialog(); - dbConfigChanged = dialogS.isChanged(); - break; - - case POSTGRESQL: - EamPostgresSettingsDialog dialogP = new EamPostgresSettingsDialog(); - dbConfigChanged = dialogP.isChanged(); - break; - - default: - JOptionPane.showMessageDialog(null, Bundle.GlobalSettingsPanel_configureButton_errorLabel(), - Bundle.GlobalSettingsPanel_configureButton_errorTitle(), - JOptionPane.ERROR_MESSAGE); - break; - } - - if (dbConfigChanged) { - if (initiallyEnabled || dbConfigured) { - enableButtonSubComponents(false); - } - dbConfigured = true; - firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - } - }//GEN-LAST:event_bnConfigureDatabaseSettingsActionPerformed - - /** - * When there is a change to the combobox, update the selectedPlatform. - * - * @param evt - */ - @SuppressWarnings({"unchecked cast", "unchecked"}) - private void comboboxSelectDatabaseTypeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboboxSelectDatabaseTypeActionPerformed - if (comboboxSelectDatabaseTypeActionListenerActive) { - JComboBox cb = (JComboBox) evt.getSource(); - String platformName = (String) cb.getSelectedItem(); - EamDbPlatformEnum.setSelectedPlatform(platformName); - } - }//GEN-LAST:event_comboboxSelectDatabaseTypeActionPerformed - private void bnManageTagsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnManageTagsActionPerformed ManageTagsDialog dialog = new ManageTagsDialog(); firePropertyChange(OptionsPanelController.PROP_VALID, null, null); }//GEN-LAST:event_bnManageTagsActionPerformed private void bnManageTypesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnManageTypesActionPerformed - ManageArtifactTypesDialog dialogT = new ManageArtifactTypesDialog(); + ManageArtifactTypesDialog dialog = new ManageArtifactTypesDialog(); firePropertyChange(OptionsPanelController.PROP_VALID, null, null); }//GEN-LAST:event_bnManageTypesActionPerformed + private void bnDbConfigureActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnDbConfigureActionPerformed + EamDbSettingsDialog dialog = new EamDbSettingsDialog(); + load(); // reload db settings content and update buttons + }//GEN-LAST:event_bnDbConfigureActionPerformed + @Override + @Messages({"GlobalSettingsPanel.validationerrMsg.mustConfigure=Configure the database to enable this module."}) public void load() { tbOops.setText(""); enableAllSubComponents(false); - - initiallyEnabled = Boolean.valueOf(ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.enabled")); // NON-NLS - cbEnableEnterpriseArtifactsManager.setSelected(initiallyEnabled); // NON-NLS - String selectedPlatformString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.selectedPlatform"); // NON-NLS - dbConfigured = selectedPlatformString != null; - - if (dbConfigured) { - comboboxSelectDatabaseTypeActionListenerActive = false; // don't fire action listener while configuring combobox content - comboboxSelectDatabaseType.setSelectedIndex(EamDbPlatformEnum.getSelectedPlatform().ordinal()); - comboboxSelectDatabaseTypeActionListenerActive = true; // don't fire action listener while loading combobox content - } - if (this.valid() && initiallyEnabled) { - enableButtonSubComponents(true); + EamDbPlatformEnum selectedPlatform = EamDbPlatformEnum.getSelectedPlatform(); + + switch (selectedPlatform) { + case POSTGRESQL: + PostgresEamDbSettings dbSettingsPg = new PostgresEamDbSettings(); + lbDbPlatformValue.setText(EamDbPlatformEnum.POSTGRESQL.toString()); + lbDbNameValue.setText(dbSettingsPg.getDbName()); + lbDbLocationValue.setText(dbSettingsPg.getHost()); + enableAllSubComponents(true); + break; + case SQLITE: + SqliteEamDbSettings dbSettingsSqlite = new SqliteEamDbSettings(); + lbDbPlatformValue.setText(EamDbPlatformEnum.SQLITE.toString()); + lbDbNameValue.setText(dbSettingsSqlite.getDbName()); + lbDbLocationValue.setText(dbSettingsSqlite.getDbDirectory()); + enableAllSubComponents(true); + break; + default: + lbDbPlatformValue.setText(EamDbPlatformEnum.DISABLED.toString()); + lbDbNameValue.setText(""); + lbDbLocationValue.setText(""); + enableDatabaseConfigureButton(true); + tbOops.setText(Bundle.GlobalSettingsPanel_validationerrMsg_mustConfigure()); + break; } + this.ingestStateUpdated(); } @Override public void store() { // Click OK or Apply on Options Panel - saveSettings(); } /** - * Validates that the form is filled out correctly for our usage. + * Validates that the dialog/panel is filled out correctly for our usage. * * @return true if it's okay, false otherwise. */ - boolean valid() { - tbOops.setText(""); - - if (cbEnableEnterpriseArtifactsManager.isSelected()) { - return validateDatabaseSettings(); - } else { - return true; - } - } - - /** - * Validate the Database Settings panel - * - * @return true or false - */ - @Messages({"GlobalSettingsPanel.validate.mustConfigureDb.text=You must configure the database."}) - private boolean validateDatabaseSettings() { - if (!dbConfigured) { - tbOops.setText(Bundle.GlobalSettingsPanel_validate_mustConfigureDb_text()); - return false; - } - + public boolean valid() { return true; } @Override public void saveSettings() { // Click OK on Global Settings Panel - ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.enabled", Boolean.toString(cbEnableEnterpriseArtifactsManager.isSelected())); // NON-NLS - if (cbEnableEnterpriseArtifactsManager.isSelected()) { - EamDbPlatformEnum.saveSelectedPlatform(); - EamDb dbManager = EamDb.getInstance(); - dbManager.updateSettings(); - enableButtonSubComponents(true); - } } @Override @@ -426,7 +323,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i } }; - @Messages({"GlobalSettingsPanel.validationErrMsg.ingestRunning=Cannot change settings while ingest is running."}) + @Messages({"GlobalSettingsPanel.validationErrMsg.ingestRunning=You cannot change settings while ingest is running."}) private void ingestStateUpdated() { if (!SwingUtilities.isEventDispatchThread()) { SwingUtilities.invokeLater(() -> { @@ -437,13 +334,8 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i } if (IngestManager.getInstance().isIngestRunning()) { - cbEnableEnterpriseArtifactsManager.setEnabled(false); tbOops.setText(Bundle.GlobalSettingsPanel_validationErrMsg_ingestRunning()); enableAllSubComponents(false); - } else { - cbEnableEnterpriseArtifactsManager.setEnabled(true); - tbOops.setText(""); - enableAllSubComponents(cbEnableEnterpriseArtifactsManager.isSelected()); } } @@ -456,22 +348,20 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i * @return True */ private boolean enableAllSubComponents(Boolean enable) { - enableDatabaseSubComponents(enable); + enableDatabaseConfigureButton(enable); enableButtonSubComponents(enable); return true; } /** - * Wrapper around each of the enableXYZ methods that configure the database - * to enable/disable them all at the same time. + * Enable the Configure button * * @param enable * * @return True */ - private boolean enableDatabaseSubComponents(Boolean enable) { - enableDatabasePlatformComboBox(enable); - enableConfigureDatabasePlatformButton(enable); + private boolean enableDatabaseConfigureButton(Boolean enable) { + bnDbConfigure.setEnabled(enable); return true; } @@ -484,84 +374,25 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i * @return True */ private boolean enableButtonSubComponents(Boolean enable) { - enableManageCorrelationTypesButton(enable); - enableImportGloballyKnownArtifactsButton(enable); - enableManageTagsButton(enable); + bnManageTypes.setEnabled(enable); + bnImportDatabase.setEnabled(enable); + bnManageTags.setEnabled(enable); return true; } - /** - * Enables the ComboBox used to select the database platform. - * - * @param enable - * - * @return True or False - */ - private boolean enableDatabasePlatformComboBox(Boolean enable) { - comboboxSelectDatabaseType.setEnabled(enable); - return enable; - } - - /** - * Enables the "Configure" button used to configure the database platform. - * - * @param enable - * - * @return True or False - */ - private boolean enableConfigureDatabasePlatformButton(Boolean enable) { - bnConfigureDatabaseSettings.setEnabled(enable); - return enable; - } - - /** - * Enables the "Import Globally Known Artifacts" button. - * - * @param enable - * - * @return True or False - */ - private boolean enableImportGloballyKnownArtifactsButton(Boolean enable) { - bnImportDatabase.setEnabled(enable); - return enable; - } - - /** - * Enables the "Manage Artifact Types" button. - * - * @param enable - * - * @return True or False - */ - private boolean enableManageCorrelationTypesButton(Boolean enable) { - bnManageTypes.setEnabled(enable); - return enable; - } - - /** - * Enables the "Manage Tags" button. - * - * @param enable - * - * @return True or False - */ - private boolean enableManageTagsButton(Boolean enable) { - bnManageTags.setEnabled(enable); - return enable; - } - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton bnConfigureDatabaseSettings; + private javax.swing.JButton bnDbConfigure; private javax.swing.JButton bnImportDatabase; private javax.swing.JButton bnManageTags; private javax.swing.JButton bnManageTypes; - private javax.swing.JCheckBox cbEnableEnterpriseArtifactsManager; - private javax.swing.JComboBox comboboxSelectDatabaseType; - private javax.swing.JScrollPane jScrollPane; - private javax.swing.JLabel lbDatabasePlatform; - private javax.swing.JPanel pnDatabaseConnectionSettings; - private javax.swing.JPanel pnOverallPanel; - private javax.swing.JPanel pnSettings; + private javax.swing.JLabel lbDbLocationLabel; + private javax.swing.JLabel lbDbLocationValue; + private javax.swing.JLabel lbDbNameLabel; + private javax.swing.JLabel lbDbNameValue; + private javax.swing.JLabel lbDbPlatformTypeLabel; + private javax.swing.JLabel lbDbPlatformValue; + private javax.swing.JPanel pnDatabaseConfiguration; + private javax.swing.JPanel pnDatabaseContentButtons; private javax.swing.JTextField tbOops; // End of variables declaration//GEN-END:variables } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ImportHashDatabaseDialog.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ImportHashDatabaseDialog.java index e1927401cd..8e40524923 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ImportHashDatabaseDialog.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ImportHashDatabaseDialog.java @@ -119,8 +119,11 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { orgs = dbManager.getOrganizations(); orgs.forEach((org) -> { comboboxSourceOrganization.addItem(org.getName()); - selectedOrg = orgs.get(0); }); + if (!orgs.isEmpty()) { + selectedOrg = orgs.get(0); + } + valid(); } catch (EamDbException ex) { LOGGER.log(Level.SEVERE, "Failure populating combobox with organizations.", ex); } @@ -178,12 +181,12 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { public boolean valid() { lbWarningMsg.setText(""); EamDb dbManager = EamDb.getInstance(); - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { lbWarningMsg.setText(Bundle.ImportHashDatabaseDialog_validation_notEnabled()); return false; } - return enableOkButton(checkFields()); + return enableOkButton(checkFields() && null != selectedOrg); } /** @@ -545,6 +548,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { return; } } + valid(); }//GEN-LAST:event_comboboxSourceOrganizationActionPerformed @NbBundle.Messages({"ImportHashDatabaseDialog.ImportHashDatabaseWorker.displayName=Importing Hash Database"}) @@ -561,7 +565,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { this.knownStatus = knownStatus; this.globalSetID = globalSetID; - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { throw new EamDbException("Enterprise artifacts manager database settings were not properly initialized"); // NON-NLS } }