/*
* Autopsy Forensic Browser
*
* Copyright 2012 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.report;
import java.awt.BorderLayout;
import java.awt.Component;
import java.util.ArrayList;
import java.util.Collections;
import static java.util.Collections.swap;
import java.util.Comparator;
import java.util.List;
import java.util.logging.Level;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.python.JythonModuleLoader;
final class ReportVisualPanel1 extends JPanel implements ListSelectionListener {
private static final Logger logger = Logger.getLogger(ReportVisualPanel1.class.getName());
private ReportWizardPanel1 wizPanel;
private List<ReportModule> modules = new ArrayList<>();
private List<GeneralReportModule> generalModules = new ArrayList<>();
private List<TableReportModule> tableModules = new ArrayList<>();
private List<FileReportModule> fileModules = new ArrayList<>();
private Integer selectedIndex;
/**
* Creates new form ReportVisualPanel1
*/
public ReportVisualPanel1(ReportWizardPanel1 wizPanel) {
this.wizPanel = wizPanel;
initComponents();
configurationPanel.setLayout(new BorderLayout());
descriptionTextPane.setEditable(false);
initModules();
}
// Initialize the list of ReportModules
private void initModules() {
for (TableReportModule module : Lookup.getDefault().lookupAll(TableReportModule.class)) {
if (moduleIsValid(module)) {
tableModules.add(module);
modules.add(module);
} else {
popupWarning(module);
}
}
for (GeneralReportModule module : Lookup.getDefault().lookupAll(GeneralReportModule.class)) {
if (moduleIsValid(module)) {
generalModules.add(module);
modules.add(module);
} else {
popupWarning(module);
}
}
for (GeneralReportModule module : JythonModuleLoader.getGeneralReportModules()) {
if (moduleIsValid(module)) {
generalModules.add(module);
modules.add(module);
} else {
popupWarning(module);
}
}
for (FileReportModule module : Lookup.getDefault().lookupAll(FileReportModule.class)) {
if (moduleIsValid(module)) {
fileModules.add(module);
modules.add(module);
} else {
popupWarning(module);
}
}
Collections.sort(modules, new Comparator<ReportModule>() {
@Override
public int compare(ReportModule rm1, ReportModule rm2) {
// our theory is that the report table modules are more common, so they go on top
boolean rm1isTable = (rm1 instanceof TableReportModule);
boolean rm2isTable = (rm2 instanceof TableReportModule);
if (rm1isTable && !rm2isTable) {
return -1;
}
if (!rm1isTable && rm2isTable) {
return 1;
}
return rm1.getName().compareTo(rm2.getName());
}
});
// Results-HTML should always be first in the list of Report Modules.
int indexOfHTMLReportModule = 0;
for (ReportModule module : modules) {
if (module instanceof ReportHTML) {
break;
}
indexOfHTMLReportModule++;
}
swap(modules, indexOfHTMLReportModule, 0);
modulesJList.getSelectionModel().addListSelectionListener(this);
modulesJList.setCellRenderer(new ModuleCellRenderer());
modulesJList.setListData(modules.toArray(new ReportModule[modules.size()]));
selectedIndex = 0;
modulesJList.setSelectedIndex(selectedIndex);
}
// Make sure that the report module has a valid non-null name.
private boolean moduleIsValid(ReportModule module) {
return module.getName() != null && !module.getName().isEmpty()
&& module.getRelativeFilePath() != null;
}
private void popupWarning(ReportModule module) {
String moduleClassName = module.getClass().getSimpleName();
logger.log(Level.WARNING, "Invalid ReportModule: {0}", moduleClassName); // NON_NLS NON-NLS
DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message(
NbBundle.getMessage(ReportVisualPanel1.class, "ReportVisualPanel1.invalidModuleWarning", moduleClassName),
NotifyDescriptor.ERROR_MESSAGE));
}
@Override
public String getName() {
return NbBundle.getMessage(this.getClass(), "ReportVisualPanel1.getName.text");
}
public ReportModule getSelectedModule() {
return modules.get(selectedIndex);
}
/**
* Get the Selection status of the TableModules.
*
* @return
*/
TableReportModule getTableModule() {
ReportModule mod = getSelectedModule();
if (tableModules.contains(mod)) {
return (TableReportModule) mod;
}
return null;
}
/**
* Get the selection status of the GeneralReportModules.
*
* @return
*/
GeneralReportModule getGeneralModule() {
ReportModule mod = getSelectedModule();
if (generalModules.contains(mod)) {
return (GeneralReportModule) mod;
}
return null;
}
/**
* Get the selection status of the FileReportModules.
*
* @return
*/
FileReportModule getFileModule() {
ReportModule mod = getSelectedModule();
if (fileModules.contains(mod)) {
return (FileReportModule) mod;
}
return null;
}
/**
* 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.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
reportModulesLabel = new javax.swing.JLabel();
configurationPanel = new javax.swing.JPanel();
descriptionScrollPane = new javax.swing.JScrollPane();
descriptionTextPane = new javax.swing.JTextPane();
modulesScrollPane = new javax.swing.JScrollPane();
modulesJList = new javax.swing.JList<>();
setPreferredSize(new java.awt.Dimension(650, 250));
org.openide.awt.Mnemonics.setLocalizedText(reportModulesLabel, org.openide.util.NbBundle.getMessage(ReportVisualPanel1.class, "ReportVisualPanel1.reportModulesLabel.text")); // NOI18N
configurationPanel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(125, 125, 125)));
javax.swing.GroupLayout configurationPanelLayout = new javax.swing.GroupLayout(configurationPanel);
configurationPanel.setLayout(configurationPanelLayout);
configurationPanelLayout.setHorizontalGroup(
configurationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 432, Short.MAX_VALUE)
);
configurationPanelLayout.setVerticalGroup(
configurationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 168, Short.MAX_VALUE)
);
descriptionScrollPane.setBorder(null);
descriptionTextPane.setBackground(new java.awt.Color(240, 240, 240));
descriptionTextPane.setBorder(null);
descriptionScrollPane.setViewportView(descriptionTextPane);
modulesJList.setBackground(new java.awt.Color(240, 240, 240));
modulesJList.setModel(new javax.swing.AbstractListModel<ReportModule>() {
ReportModule[] modules = {};
public int getSize() { return modules.length; }
public ReportModule getElementAt(int i) { return modules[i]; }
});
modulesScrollPane.setViewportView(modulesJList);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(reportModulesLabel)
.addComponent(modulesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 190, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(configurationPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(descriptionScrollPane))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(reportModulesLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(descriptionScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(configurationPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addComponent(modulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 208, Short.MAX_VALUE))
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel configurationPanel;
private javax.swing.JScrollPane descriptionScrollPane;
private javax.swing.JTextPane descriptionTextPane;
private javax.swing.JList<ReportModule> modulesJList;
private javax.swing.JScrollPane modulesScrollPane;
private javax.swing.JLabel reportModulesLabel;
// End of variables declaration//GEN-END:variables
@Override
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting()) {
return;
}
configurationPanel.removeAll();
ListSelectionModel m = (ListSelectionModel) e.getSource();
// single selection, so max selection index is the only one selected.
selectedIndex = m.getMaxSelectionIndex();
JPanel panel = new DefaultReportConfigurationPanel();
ReportModule module = modules.get(selectedIndex);
boolean generalModuleSelected = false;
if (module instanceof GeneralReportModule) {
JPanel generalPanel = ((GeneralReportModule) module).getConfigurationPanel();
panel = (generalPanel == null) ? new JPanel() : generalPanel;
generalModuleSelected = true;
}
descriptionTextPane.setText(module.getDescription());
configurationPanel.add(panel, BorderLayout.CENTER);
configurationPanel.revalidate();
wizPanel.setNext(!generalModuleSelected);
wizPanel.setFinish(generalModuleSelected);
}
private class ModuleCellRenderer extends JRadioButton implements ListCellRenderer<ReportModule> {
@Override
public Component getListCellRendererComponent(JList<? extends ReportModule> list, ReportModule value, int index, boolean isSelected, boolean cellHasFocus) {
this.setText(value.getName());
this.setEnabled(true);
this.setSelected(isSelected);
return this;
}
}
}