19 package org.sleuthkit.autopsy.keywordsearch;
 
   21 import java.awt.Component;
 
   22 import java.awt.Cursor;
 
   23 import java.awt.EventQueue;
 
   24 import java.awt.event.ActionEvent;
 
   25 import java.awt.event.ActionListener;
 
   26 import java.beans.PropertyChangeEvent;
 
   27 import java.beans.PropertyChangeListener;
 
   28 import java.util.ArrayList;
 
   29 import java.util.HashSet;
 
   30 import java.util.Iterator;
 
   31 import java.util.List;
 
   33 import java.util.logging.Level;
 
   34 import javax.swing.JCheckBox;
 
   35 import javax.swing.JTable;
 
   36 import javax.swing.ListSelectionModel;
 
   37 import javax.swing.event.ListSelectionEvent;
 
   38 import javax.swing.event.ListSelectionListener;
 
   39 import javax.swing.table.AbstractTableModel;
 
   40 import javax.swing.table.TableCellRenderer;
 
   41 import javax.swing.table.TableColumn;
 
   42 import org.openide.util.NbBundle;
 
   43 import org.openide.util.actions.SystemAction;
 
   51 @SuppressWarnings(
"PMD.SingularField") 
 
   52 class DropdownListSearchPanel extends AdHocSearchPanel {
 
   54     private static final Logger logger = Logger.getLogger(DropdownListSearchPanel.class.getName());
 
   55     private static DropdownListSearchPanel instance;
 
   56     private XmlKeywordSearchList loader;
 
   57     private final KeywordListsTableModel listsTableModel;
 
   58     private final KeywordsTableModel keywordsTableModel;
 
   59     private ActionListener searchAddListener;
 
   60     private boolean ingestRunning;
 
   65     private DropdownListSearchPanel() {
 
   66         listsTableModel = 
new KeywordListsTableModel();
 
   67         keywordsTableModel = 
new KeywordsTableModel();
 
   69         customizeComponents();
 
   70         dataSourceList.setModel(getDataSourceListModel());
 
   72         dataSourceList.addListSelectionListener((ListSelectionEvent evt) -> {
 
   73             firePropertyChange(Bundle.DropdownSingleTermSearchPanel_selected(), null, null);
 
   77     static synchronized DropdownListSearchPanel getDefault() {
 
   78         if (instance == null) {
 
   79             instance = 
new DropdownListSearchPanel();
 
   84     private void customizeComponents() {
 
   85         listsTable.setTableHeader(null);
 
   86         listsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
 
   88         final int leftWidth = leftPane.getPreferredSize().width;
 
   90         for (
int i = 0; i < listsTable.getColumnCount(); i++) {
 
   91             column = listsTable.getColumnModel().getColumn(i);
 
   93                 column.setPreferredWidth(((
int) (leftWidth * 0.10)));
 
   94                 column.setCellRenderer(
new LeftCheckBoxRenderer());
 
   96                 column.setPreferredWidth(((
int) (leftWidth * 0.89)));
 
   99         final int rightWidth = rightPane.getPreferredSize().width;
 
  100         for (
int i = 0; i < keywordsTable.getColumnCount(); i++) {
 
  101             column = keywordsTable.getColumnModel().getColumn(i);
 
  103                 column.setPreferredWidth(((
int) (rightWidth * 0.60)));
 
  105                 column.setPreferredWidth(((
int) (rightWidth * 0.38)));
 
  109         loader = XmlKeywordSearchList.getCurrent();
 
  110         listsTable.getSelectionModel().addListSelectionListener(
new ListSelectionListener() {
 
  112             public void valueChanged(ListSelectionEvent e) {
 
  113                 ListSelectionModel listSelectionModel = (ListSelectionModel) e.getSource();
 
  114                 if (!listSelectionModel.isSelectionEmpty()) {
 
  115                     int index = listSelectionModel.getMinSelectionIndex();
 
  116                     KeywordList list = listsTableModel.getListAt(index);
 
  117                     keywordsTableModel.resync(list);
 
  119                     keywordsTableModel.deleteAll();
 
  124         ingestRunning = IngestManager.getInstance().isIngestRunning();
 
  127         IngestManager.getInstance().addIngestJobEventListener(
new PropertyChangeListener() {
 
  129             public void propertyChange(PropertyChangeEvent evt) {
 
  130                 Object source = evt.getSource();
 
  131                 if (source instanceof String && ((String) source).equals(
"LOCAL")) { 
 
  132                     EventQueue.invokeLater(() -> {
 
  133                         ingestRunning = IngestManager.getInstance().isIngestRunning();
 
  140         searchAddListener = 
new ActionListener() {
 
  142             public void actionPerformed(ActionEvent e) {
 
  144                     IngestSearchRunner.getInstance().addKeywordListsToAllJobs(listsTableModel.getSelectedLists());
 
  145                     logger.log(Level.INFO, 
"Submitted enqueued lists to ingest"); 
 
  152         searchAddButton.addActionListener(searchAddListener);
 
  155     private void updateComponents() {
 
  156         ingestRunning = IngestManager.getInstance().isIngestRunning();
 
  158             searchAddButton.setText(NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsViewerPanel.initIngest.addIngestTitle"));
 
  159             searchAddButton.setToolTipText(NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsViewerPanel.initIngest.addIngestMsg"));
 
  162             searchAddButton.setText(NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsViewerPanel.initIngest.searchIngestTitle"));
 
  163             searchAddButton.setToolTipText(NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsViewerPanel.initIngest.addIdxSearchMsg"));
 
  165         listsTableModel.resync();
 
  166         updateIngestIndexLabel();
 
  168         jSaveSearchResults.setSelected(
true);
 
  171     private void updateIngestIndexLabel() {
 
  173             ingestIndexLabel.setText(NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsViewerPanel.initIngest.ongoingIngestMsg", filesIndexed));
 
  175             ingestIndexLabel.setText(NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsViewerPanel.initIngest.fileIndexCtMsg", filesIndexed));
 
  180     protected void postFilesIndexedChange() {
 
  181         updateIngestIndexLabel();
 
  188         listsTableModel.resync();
 
  196     @SuppressWarnings(
"unchecked")
 
  198     private 
void initComponents() {
 
  200         jSplitPane1 = 
new javax.swing.JSplitPane();
 
  201         leftPane = 
new javax.swing.JScrollPane();
 
  202         listsTable = 
new javax.swing.JTable();
 
  203         rightPane = 
new javax.swing.JScrollPane();
 
  204         keywordsTable = 
new javax.swing.JTable();
 
  205         manageListsButton = 
new javax.swing.JButton();
 
  206         searchAddButton = 
new javax.swing.JButton();
 
  207         ingestIndexLabel = 
new javax.swing.JLabel();
 
  208         dataSourceCheckBox = 
new javax.swing.JCheckBox();
 
  209         jScrollPane1 = 
new javax.swing.JScrollPane();
 
  210         dataSourceList = 
new javax.swing.JList<>();
 
  211         jSaveSearchResults = 
new javax.swing.JCheckBox();
 
  213         setFont(getFont().deriveFont(getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  215         jSplitPane1.setFont(leftPane.getFont());
 
  217         leftPane.setFont(leftPane.getFont().deriveFont(leftPane.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  218         leftPane.setMinimumSize(
new java.awt.Dimension(150, 23));
 
  219         leftPane.setOpaque(
false);
 
  221         listsTable.setBackground(
new java.awt.Color(240, 240, 240));
 
  222         listsTable.setFont(listsTable.getFont().deriveFont(listsTable.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  223         listsTable.setModel(listsTableModel);
 
  224         listsTable.setShowHorizontalLines(
false);
 
  225         listsTable.setShowVerticalLines(
false);
 
  226         listsTable.getTableHeader().setReorderingAllowed(
false);
 
  227         leftPane.setViewportView(listsTable);
 
  229         jSplitPane1.setLeftComponent(leftPane);
 
  231         rightPane.setFont(rightPane.getFont().deriveFont(rightPane.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  232         rightPane.setOpaque(
false);
 
  234         keywordsTable.setBackground(
new java.awt.Color(240, 240, 240));
 
  235         keywordsTable.setFont(keywordsTable.getFont().deriveFont(keywordsTable.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  236         keywordsTable.setModel(keywordsTableModel);
 
  237         keywordsTable.setGridColor(
new java.awt.Color(153, 153, 153));
 
  238         rightPane.setViewportView(keywordsTable);
 
  240         jSplitPane1.setRightComponent(rightPane);
 
  242         manageListsButton.setFont(manageListsButton.getFont().deriveFont(manageListsButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  243         manageListsButton.setText(
org.openide.util.NbBundle.getMessage(DropdownListSearchPanel.class, 
"KeywordSearchListsViewerPanel.manageListsButton.text")); 
 
  244         manageListsButton.setToolTipText(
org.openide.util.NbBundle.getMessage(DropdownListSearchPanel.class, 
"KeywordSearchListsViewerPanel.manageListsButton.toolTipText")); 
 
  245         manageListsButton.addActionListener(
new java.awt.event.ActionListener() {
 
  246             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  247                 manageListsButtonActionPerformed(evt);
 
  251         searchAddButton.setFont(searchAddButton.getFont().deriveFont(searchAddButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  252         searchAddButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/keywordsearch/search-icon.png"))); 
 
  253         searchAddButton.setText(
org.openide.util.NbBundle.getMessage(DropdownListSearchPanel.class, 
"KeywordSearchListsViewerPanel.searchAddButton.text")); 
 
  254         searchAddButton.addActionListener(
new java.awt.event.ActionListener() {
 
  255             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  256                 searchAddButtonActionPerformed(evt);
 
  260         ingestIndexLabel.setFont(ingestIndexLabel.getFont().deriveFont(ingestIndexLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 10));
 
  261         ingestIndexLabel.setText(
org.openide.util.NbBundle.getMessage(DropdownListSearchPanel.class, 
"KeywordSearchListsViewerPanel.ingestIndexLabel.text")); 
 
  263         dataSourceCheckBox.setText(
org.openide.util.NbBundle.getMessage(DropdownListSearchPanel.class, 
"DropdownListSearchPanel.dataSourceCheckBox.text")); 
 
  264         dataSourceCheckBox.addActionListener(
new java.awt.event.ActionListener() {
 
  265             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  266                 dataSourceCheckBoxActionPerformed(evt);
 
  270         dataSourceList.setMinimumSize(
new java.awt.Dimension(0, 200));
 
  271         jScrollPane1.setViewportView(dataSourceList);
 
  273         jSaveSearchResults.setText(
org.openide.util.NbBundle.getMessage(DropdownListSearchPanel.class, 
"DropdownListSearchPanel.jSaveSearchResults.text")); 
 
  274         jSaveSearchResults.setToolTipText(
org.openide.util.NbBundle.getMessage(DropdownListSearchPanel.class, 
"DropdownListSearchPanel.jSaveSearchResults.toolTipText")); 
 
  276         javax.swing.GroupLayout layout = 
new javax.swing.GroupLayout(
this);
 
  277         this.setLayout(layout);
 
  278         layout.setHorizontalGroup(
 
  279             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  280             .addComponent(jSplitPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
 
  281             .addComponent(jScrollPane1)
 
  282             .addGroup(layout.createSequentialGroup()
 
  283                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  284                     .addComponent(dataSourceCheckBox)
 
  285                     .addComponent(jSaveSearchResults)
 
  286                     .addGroup(layout.createSequentialGroup()
 
  287                         .addComponent(searchAddButton)
 
  288                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  289                         .addComponent(manageListsButton)
 
  290                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  291                         .addComponent(ingestIndexLabel)))
 
  292                 .addGap(0, 120, Short.MAX_VALUE))
 
  295         layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, 
new java.awt.Component[] {manageListsButton, searchAddButton});
 
  297         layout.setVerticalGroup(
 
  298             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  299             .addGroup(layout.createSequentialGroup()
 
  300                 .addComponent(jSplitPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 183, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  301                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  302                 .addComponent(dataSourceCheckBox)
 
  303                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  304                 .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 65, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  305                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  306                 .addComponent(jSaveSearchResults)
 
  307                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  308                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  309                     .addComponent(manageListsButton)
 
  310                     .addComponent(searchAddButton)
 
  311                     .addComponent(ingestIndexLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 13, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  316     private void manageListsButtonActionPerformed(java.awt.event.ActionEvent evt) {
 
  317         SystemAction.get(KeywordSearchConfigurationAction.class).performAction();
 
  320     private void dataSourceCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {
 
  321         updateDataSourceListModel();
 
  324     private void searchAddButtonActionPerformed(java.awt.event.ActionEvent evt) {
 
  329     private javax.swing.JCheckBox dataSourceCheckBox;
 
  330     private javax.swing.JList<String> dataSourceList;
 
  331     private javax.swing.JLabel ingestIndexLabel;
 
  332     private javax.swing.JCheckBox jSaveSearchResults;
 
  333     private javax.swing.JScrollPane jScrollPane1;
 
  334     private javax.swing.JSplitPane jSplitPane1;
 
  335     private javax.swing.JTable keywordsTable;
 
  336     private javax.swing.JScrollPane leftPane;
 
  337     private javax.swing.JTable listsTable;
 
  338     private javax.swing.JButton manageListsButton;
 
  339     private javax.swing.JScrollPane rightPane;
 
  340     private javax.swing.JButton searchAddButton;
 
  343     private void searchAction(ActionEvent e) {
 
  344         setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
 
  347             search(jSaveSearchResults.isSelected());
 
  354     List<KeywordList> getKeywordLists() {
 
  355         return listsTableModel.getSelectedListsL();
 
  358     void addSearchButtonActionListener(ActionListener al) {
 
  359         searchAddButton.addActionListener(al);
 
  367     Set<Long> getDataSourcesSelected() {
 
  368         Set<Long> dataSourceObjIdSet = 
new HashSet<>();
 
  369         for (Long key : getDataSourceMap().keySet()) {
 
  370             String value = getDataSourceMap().get(key);
 
  371             for (String dataSource : this.dataSourceList.getSelectedValuesList()) {
 
  372                 if (value.equals(dataSource)) {
 
  373                     dataSourceObjIdSet.add(key);
 
  377         return dataSourceObjIdSet;
 
  383         private final XmlKeywordSearchList listsHandle = XmlKeywordSearchList.getCurrent();
 
  384         private final List<ListTableEntry> listData = 
new ArrayList<>();
 
  393             return listData.size();
 
  401                     ret = NbBundle.getMessage(this.getClass(), 
"KeywordSearch.selectedColLbl");
 
  404                     ret = NbBundle.getMessage(this.getClass(), 
"KeywordSearch.nameColLbl");
 
  417             Iterator<ListTableEntry> it = listData.iterator();
 
  418             for (
int i = 0; i <= rowIndex; ++i) {
 
  422                 switch (columnIndex) {
 
  424                         ret = (Object) entry.selected;
 
  427                         ret = (Object) entry.name;
 
  438             return (columnIndex == 0 && !ingestRunning);
 
  442         public void setValueAt(Object aValue, 
int rowIndex, 
int columnIndex) {
 
  443             if (columnIndex == 0) {
 
  445                 Iterator<ListTableEntry> it = listData.iterator();
 
  446                 for (
int i = 0; i <= rowIndex; i++) {
 
  450                     entry.selected = (Boolean) aValue;
 
  461             return getValueAt(0, c).getClass();
 
  464         List<String> getAllLists() {
 
  465             List<String> ret = 
new ArrayList<>();
 
  466             for (ListTableEntry e : listData) {
 
  472         KeywordList getListAt(
int rowIndex) {
 
  473             return listsHandle.getList((String) getValueAt(rowIndex, 1));
 
  476         List<String> getSelectedLists() {
 
  477             List<String> ret = 
new ArrayList<>();
 
  478             for (ListTableEntry e : listData) {
 
  486         List<KeywordList> getSelectedListsL() {
 
  487             List<KeywordList> ret = 
new ArrayList<>();
 
  488             for (String s : getSelectedLists()) {
 
  489                 ret.add(listsHandle.getList(s));
 
  494         boolean listExists(String list) {
 
  495             List<String> all = getAllLists();
 
  496             return all.contains(list);
 
  502             addLists(listsHandle.getListsL());
 
  503             fireTableDataChanged();
 
  509                 if (!listExists(list.getName())) {
 
  522                 this.name = list.getName();
 
  524                     this.selected = list.getUseForIngest();
 
  526                     this.selected = 
false;
 
  532                 return this.name.compareTo(e.name);
 
  539         List<KeywordTableEntry> listData = 
new ArrayList<>();
 
  543             return listData.size();
 
  556                     ret = NbBundle.getMessage(this.getClass(), 
"KeywordSearch.nameColLbl");
 
  559                     ret = NbBundle.getMessage(this.getClass(), 
"KeywordSearch.typeColLbl");
 
  572             Iterator<KeywordTableEntry> it = listData.iterator();
 
  573             for (
int i = 0; i <= rowIndex; ++i) {
 
  577                 switch (columnIndex) {
 
  579                         ret = (Object) entry.name;
 
  582                         ret = (Object) entry.keywordType;
 
  597         public void setValueAt(Object aValue, 
int rowIndex, 
int columnIndex) {
 
  602             return getValueAt(0, c).getClass();
 
  608                 listData.add(
new KeywordTableEntry(k));
 
  610             fireTableDataChanged();
 
  615             fireTableDataChanged();
 
  626                 this.keywordType = keyword.getSearchTermType();
 
  631                 return this.name.compareTo(e.name);
 
  640                 JTable table, Object value,
 
  641                 boolean isSelected, 
boolean hasFocus,
 
  642                 int row, 
int column) {
 
  644             this.setHorizontalAlignment(JCheckBox.CENTER);
 
  645             this.setVerticalAlignment(JCheckBox.CENTER);
 
  647             setEnabled(!ingestRunning);
 
  649             boolean selected = (Boolean) table.getModel().getValueAt(row, 0);
 
  650             setSelected(selected);
 
  653                 setBackground(listsTable.getSelectionBackground());
 
  655                 setBackground(listsTable.getBackground());
 
  665     @NbBundle.Messages({
"DropdownListSearchPanel.selected=Ad Hoc Search data source filter is selected"})
 
  666     void updateDataSourceListModel() {
 
  667         getDataSourceListModel().removeAllElements();
 
  668         for (String dsName : getDataSourceArray()) {
 
  669             getDataSourceListModel().addElement(dsName);
 
  671         setComponentsEnabled();
 
  672         firePropertyChange(Bundle.DropdownListSearchPanel_selected(), null, null);
 
  679     private void setComponentsEnabled() {
 
  681         if (getDataSourceListModel().size() > 1) {
 
  682             this.dataSourceCheckBox.setEnabled(
true);
 
  684             boolean enabled = this.dataSourceCheckBox.isSelected();
 
  685             this.dataSourceList.setEnabled(enabled);
 
  687                 this.dataSourceList.setSelectionInterval(0, this.dataSourceList.getModel().getSize()-1);
 
  689                 this.dataSourceList.setSelectedIndices(
new int[0]);
 
  692             this.dataSourceCheckBox.setEnabled(
false);
 
  693             this.dataSourceCheckBox.setSelected(
false);
 
  694             this.dataSourceList.setEnabled(
false);
 
  695             this.dataSourceList.setSelectedIndices(
new int[0]);
 
void setValueAt(Object aValue, int rowIndex, int columnIndex)
 
String getColumnName(int column)
 
int compareTo(ListTableEntry e)
 
boolean isCellEditable(int rowIndex, int columnIndex)
 
Class<?> getColumnClass(int c)
 
void addLists(List< KeywordList > lists)
 
boolean isCellEditable(int rowIndex, int columnIndex)
 
Class<?> getColumnClass(int c)
 
Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
 
List< Keyword > getKeywords()
 
int compareTo(KeywordTableEntry e)
 
String getColumnName(int column)
 
Object getValueAt(int rowIndex, int columnIndex)
 
void setValueAt(Object aValue, int rowIndex, int columnIndex)
 
Object getValueAt(int rowIndex, int columnIndex)