19 package org.sleuthkit.autopsy.ingest;
22 import java.awt.Component;
23 import java.awt.event.ActionEvent;
24 import java.awt.event.WindowAdapter;
25 import java.awt.event.WindowEvent;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.List;
30 import java.util.logging.Level;
31 import javax.swing.DefaultComboBoxModel;
32 import javax.swing.Icon;
33 import javax.swing.ImageIcon;
34 import javax.swing.JDialog;
35 import javax.swing.JLabel;
36 import javax.swing.JTable;
37 import javax.swing.ListSelectionModel;
38 import javax.swing.SwingUtilities;
39 import javax.swing.event.ListSelectionEvent;
40 import javax.swing.table.AbstractTableModel;
41 import javax.swing.table.DefaultTableCellRenderer;
42 import javax.swing.table.TableColumn;
43 import org.openide.util.NbBundle.Messages;
62 @SuppressWarnings(
"PMD.SingularField")
65 private static final long serialVersionUID = 1L;
66 private static ImageIcon warningIcon =
new ImageIcon(
IngestJobSettingsPanel.class.getResource(
"/org/sleuthkit/autopsy/images/warning_triangle.png"));
67 private static ImageIcon infoIcon =
new ImageIcon(
IngestJobSettingsPanel.class.getResource(
"/org/sleuthkit/autopsy/images/information-frame.png"));
69 private final List<Content> dataSources =
new ArrayList<>();
70 private final List<IngestJobInfo> ingestJobs =
new ArrayList<>();
71 private final List<IngestModuleModel> modules =
new ArrayList<>();
83 this.settings = settings;
88 customizeComponents();
100 this.settings = settings;
101 this.dataSources.addAll(dataSources);
104 ingestJobs.addAll(skCase.getIngestJobs());
106 logger.log(Level.SEVERE,
"No open case", ex);
107 }
catch (TskCoreException ex) {
108 logger.log(Level.SEVERE,
"Failed to load ingest job information", ex);
114 customizeComponents();
124 List<IngestModuleTemplate> moduleTemplates =
new ArrayList<>();
127 if (module.hasModuleSettingsPanel()) {
131 moduleTemplates.add(moduleTemplate);
134 return this.settings;
137 @Messages({
"IngestJobSettingsPanel.noPerRunSettings=The selected module has no per-run settings."})
139 modulesTable.setModel(tableModel);
140 modulesTable.setTableHeader(null);
141 modulesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
147 int width = modulesScrollPane.getPreferredSize().width;
148 for (
int i = 0; i < modulesTable.getColumnCount(); ++i) {
149 TableColumn column = modulesTable.getColumnModel().getColumn(i);
151 column.setPreferredWidth(((
int) (width * 0.15)));
153 column.setCellRenderer(renderer);
154 column.setPreferredWidth(((
int) (width * 0.84)));
161 modulesTable.getSelectionModel().addListSelectionListener((ListSelectionEvent e) -> {
162 ListSelectionModel listSelectionModel = (ListSelectionModel) e.getSource();
163 if (!listSelectionModel.isSelectionEmpty()) {
164 int index = listSelectionModel.getMinSelectionIndex();
165 selectedModule = modules.get(index);
166 ingestSettingsPanel.removeAll();
167 if (null != selectedModule.getModuleSettingsPanel()) {
168 ingestSettingsPanel.add(selectedModule.getModuleSettingsPanel());
170 ingestSettingsPanel.add(
new JLabel(Bundle.IngestJobSettingsPanel_noPerRunSettings()));
172 ingestSettingsPanel.revalidate();
173 ingestSettingsPanel.repaint();
174 globalSettingsButton.setEnabled(null != selectedModule.getGlobalSettingsPanel());
175 descriptionLabel.setText(selectedModule.getDescription());
176 descriptionLabel.setToolTipText(selectedModule.getDescription());
179 modulesTable.setRowSelectionInterval(0, 0);
180 this.modulesTable.getColumnModel().getColumn(0).setMaxWidth(22);
181 this.modulesTable.getColumnModel().getColumn(1).setMaxWidth(20);
182 this.modulesTable.getColumnModel().getColumn(1).setMinWidth(20);
183 modulesTable.setRowHeight(20);
189 pastJobsButton.setEnabled(!dataSources.isEmpty() && !ingestJobs.isEmpty());
192 void setPastJobsButtonVisible(
boolean isVisible) {
193 pastJobsButton.setVisible(isVisible);
201 @SuppressWarnings(
"unchecked")
203 private
void initComponents() {
205 timeGroup =
new javax.swing.ButtonGroup();
206 modulesScrollPane =
new javax.swing.JScrollPane();
207 modulesTable =
new javax.swing.JTable();
208 jPanel1 =
new javax.swing.JPanel();
209 globalSettingsButton =
new javax.swing.JButton();
210 jSeparator2 =
new javax.swing.JSeparator();
211 descriptionLabel =
new javax.swing.JLabel();
212 jScrollPane1 =
new javax.swing.JScrollPane();
213 ingestSettingsPanel =
new javax.swing.JPanel();
214 jButtonSelectAll =
new javax.swing.JButton();
215 jButtonDeselectAll =
new javax.swing.JButton();
216 pastJobsButton =
new javax.swing.JButton();
217 fileIngestFilterLabel =
new javax.swing.JLabel();
218 fileIngestFilterComboBox =
new javax.swing.JComboBox<>();
220 setMaximumSize(
new java.awt.Dimension(5750, 3000));
221 setMinimumSize(
new java.awt.Dimension(0, 0));
222 setPreferredSize(
new java.awt.Dimension(625, 450));
224 modulesScrollPane.setBorder(javax.swing.BorderFactory.createLineBorder(
new java.awt.Color(160, 160, 160)));
225 modulesScrollPane.setMinimumSize(
new java.awt.Dimension(0, 0));
226 modulesScrollPane.setPreferredSize(
new java.awt.Dimension(160, 160));
228 modulesTable.setBackground(
new java.awt.Color(240, 240, 240));
229 modulesTable.setModel(
new javax.swing.table.DefaultTableModel(
237 modulesTable.setShowHorizontalLines(
false);
238 modulesTable.setShowVerticalLines(
false);
239 modulesScrollPane.setViewportView(modulesTable);
241 jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(
new java.awt.Color(160, 160, 160)));
242 jPanel1.setPreferredSize(
new java.awt.Dimension(338, 257));
244 globalSettingsButton.setText(
org.openide.util.NbBundle.getMessage(
IngestJobSettingsPanel.class,
"IngestJobSettingsPanel.globalSettingsButton.text"));
245 globalSettingsButton.setActionCommand(
org.openide.util.NbBundle.getMessage(
IngestJobSettingsPanel.class,
"IngestJobSettingsPanel.globalSettingsButton.actionCommand"));
246 globalSettingsButton.setEnabled(
false);
247 globalSettingsButton.addActionListener(
new java.awt.event.ActionListener() {
248 public void actionPerformed(java.awt.event.ActionEvent evt) {
249 globalSettingsButtonActionPerformed(evt);
253 descriptionLabel.setText(
"DO NOT REMOVE. This dummy text is used to anchor the inner panel's size to the outer panel, while still being expandable. Without this the expandability behavior doesn't work well. This text will never be shown, as it would only be shown when no module is selected (which is not possible).");
255 jScrollPane1.setBorder(null);
256 jScrollPane1.setPreferredSize(
new java.awt.Dimension(250, 180));
258 ingestSettingsPanel.setMinimumSize(
new java.awt.Dimension(0, 300));
259 ingestSettingsPanel.setLayout(
new javax.swing.BoxLayout(ingestSettingsPanel, javax.swing.BoxLayout.PAGE_AXIS));
260 jScrollPane1.setViewportView(ingestSettingsPanel);
262 javax.swing.GroupLayout jPanel1Layout =
new javax.swing.GroupLayout(jPanel1);
263 jPanel1.setLayout(jPanel1Layout);
264 jPanel1Layout.setHorizontalGroup(
265 jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
266 .addComponent(jSeparator2, javax.swing.GroupLayout.Alignment.TRAILING)
267 .addGroup(jPanel1Layout.createSequentialGroup()
269 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
270 .addComponent(descriptionLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
271 .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 266, Short.MAX_VALUE)
272 .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
273 .addGap(0, 0, Short.MAX_VALUE)
274 .addComponent(globalSettingsButton)))
277 jPanel1Layout.setVerticalGroup(
278 jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
279 .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
281 .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 328, Short.MAX_VALUE)
283 .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE)
285 .addComponent(descriptionLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE)
286 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
287 .addComponent(globalSettingsButton)
291 jButtonSelectAll.setText(
org.openide.util.NbBundle.getMessage(
IngestJobSettingsPanel.class,
"IngestJobSettingsPanel.jButtonSelectAll.text"));
292 jButtonSelectAll.setMargin(
new java.awt.Insets(2, 8, 2, 8));
293 jButtonSelectAll.setMaximumSize(
new java.awt.Dimension(87, 23));
294 jButtonSelectAll.setMinimumSize(
new java.awt.Dimension(87, 23));
295 jButtonSelectAll.addActionListener(
new java.awt.event.ActionListener() {
296 public void actionPerformed(java.awt.event.ActionEvent evt) {
297 jButtonSelectAllActionPerformed(evt);
301 jButtonDeselectAll.setText(
org.openide.util.NbBundle.getMessage(
IngestJobSettingsPanel.class,
"IngestJobSettingsPanel.jButtonDeselectAll.text"));
302 jButtonDeselectAll.setMargin(
new java.awt.Insets(2, 8, 2, 8));
303 jButtonDeselectAll.addActionListener(
new java.awt.event.ActionListener() {
304 public void actionPerformed(java.awt.event.ActionEvent evt) {
305 jButtonDeselectAllActionPerformed(evt);
309 pastJobsButton.setText(
org.openide.util.NbBundle.getMessage(
IngestJobSettingsPanel.class,
"IngestJobSettingsPanel.pastJobsButton.text"));
310 pastJobsButton.setMargin(
new java.awt.Insets(2, 8, 2, 8));
311 pastJobsButton.setMaximumSize(
new java.awt.Dimension(87, 23));
312 pastJobsButton.setMinimumSize(
new java.awt.Dimension(87, 23));
313 pastJobsButton.addActionListener(
new java.awt.event.ActionListener() {
314 public void actionPerformed(java.awt.event.ActionEvent evt) {
315 pastJobsButtonActionPerformed(evt);
319 fileIngestFilterLabel.setText(
org.openide.util.NbBundle.getMessage(
IngestJobSettingsPanel.class,
"IngestJobSettingsPanel.fileIngestFilterLabel.text"));
321 fileIngestFilterComboBox.setModel(
new DefaultComboBoxModel<>(getComboBoxContents()));
322 fileIngestFilterComboBox.addActionListener(
new java.awt.event.ActionListener() {
323 public void actionPerformed(java.awt.event.ActionEvent evt) {
324 fileIngestFilterComboBoxActionPerformed(evt);
328 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
329 this.setLayout(layout);
330 layout.setHorizontalGroup(
331 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
332 .addGroup(layout.createSequentialGroup()
334 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING,
false)
335 .addGroup(layout.createSequentialGroup()
336 .addComponent(jButtonSelectAll, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
337 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
338 .addComponent(jButtonDeselectAll, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
339 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
340 .addComponent(pastJobsButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
341 .addComponent(modulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
342 .addComponent(fileIngestFilterLabel)
343 .addComponent(fileIngestFilterComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
345 .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 284, Short.MAX_VALUE)
349 layout.linkSize(javax.swing.SwingConstants.HORIZONTAL,
new java.awt.Component[] {jButtonDeselectAll, jButtonSelectAll, pastJobsButton});
351 layout.setVerticalGroup(
352 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
353 .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
355 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
356 .addGroup(layout.createSequentialGroup()
357 .addComponent(fileIngestFilterLabel)
358 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
359 .addComponent(fileIngestFilterComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
360 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
361 .addComponent(modulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
362 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
363 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
364 .addComponent(jButtonSelectAll, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
365 .addComponent(jButtonDeselectAll)
366 .addComponent(pastJobsButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
367 .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 426, Short.MAX_VALUE))
376 if (selectedModule.hasGlobalSettingsPanel()) {
377 selectedModule.saveResourcesConfig();
382 dialog.addWindowListener(
new WindowAdapter() {
384 public void windowClosing(WindowEvent e) {
389 dialog.
display(selectedModule.getGlobalSettingsPanel());
393 SelectAllModules(
true);
397 SelectAllModules(
false);
399 @Messages({
"IngestJobSettingsPanel.pastJobsButton.action.frame.title=Ingest History"})
401 JDialog topFrame = (JDialog) SwingUtilities.getWindowAncestor(
this);
402 JDialog dialog =
new JDialog(topFrame, Bundle.IngestJobSettingsPanel_pastJobsButton_action_frame_title(),
false);
404 dialog.add(ingestInfo);
405 dialog.setLocationRelativeTo(topFrame);
406 dialog.setResizable(
true);
408 dialog.setVisible(
true);
416 fileIngestFilterPanel.
load();
418 final ArrayList<String> oldFilterList =
new ArrayList<>(Arrays.asList(getComboBoxContents()));
421 fileIngestFilterPanel.
store();
422 ArrayList<FilesSet> newFilterList =
new ArrayList<>();
426 logger.log(Level.SEVERE,
"Failed to get user created file ingest filters, only default available for selection", ex);
429 for (
FilesSet filter : newFilterList) {
430 if (!oldFilterList.contains(filter.getName())) {
432 filterToSelect = filter.getName();
436 fileIngestFilterComboBox.setModel(
new DefaultComboBoxModel<>(getComboBoxContents()));
438 fileIngestFilterComboBox.setSelectedItem(filterToSelect);
441 updateSelectedFilter(filterToSelect);
445 dialog.
display(fileIngestFilterPanel);
448 }
else if (evt.getActionCommand().equals(
"comboBoxChanged")) {
449 updateSelectedFilter(fileIngestFilterComboBox.getSelectedItem().toString());
458 fileIngestFilters.put(fSet.getName(), fSet);
464 logger.log(Level.SEVERE,
"Failed to get file ingest filter from combobox selection, default filter being used", ex);
479 ArrayList<String> nameList =
new ArrayList<>();
481 nameList.add(fSet.getName());
485 nameList.add(fSet.getName());
488 logger.log(Level.SEVERE,
"Failed to get user created file ingest filters for combo box, only default available for selection", ex);
491 return nameList.toArray(
new String[nameList.size()]);
496 module.setEnabled(set);
498 modulesTable.repaint();
530 this.moduleTemplate = moduleTemplate;
540 return moduleTemplate;
547 String getDescription() {
551 void setEnabled(
boolean enabled) {
555 boolean isEnabled() {
559 boolean hasModuleSettingsPanel() {
563 IngestModuleIngestJobSettingsPanel getModuleSettingsPanel() {
564 return moduleSettingsPanel;
567 boolean hasGlobalSettingsPanel() {
571 IngestModuleGlobalSettingsPanel getGlobalSettingsPanel() {
572 return globalSettingsPanel;
575 void saveResourcesConfig() {
586 private static final long serialVersionUID = 1L;
590 return modules.size();
601 switch (columnIndex) {
603 return module.isEnabled();
605 return getIcon(module);
607 return module.getName();
613 return columnIndex == 0;
617 public void setValueAt(Object aValue,
int rowIndex,
int columnIndex) {
618 if (columnIndex == 0) {
619 modules.get(rowIndex).setEnabled((
boolean) aValue);
625 return getValueAt(0, c).getClass();
629 if (dataSources.isEmpty() || ingestJobs.isEmpty()) {
632 boolean previousVersionRun =
false;
633 for (IngestJobInfo ingestJob : ingestJobs) {
634 if (ingestJob.getStatus() != IngestJobInfo.IngestJobStatusType.COMPLETED) {
637 long objectId = ingestJob.getObjectId();
638 boolean isSameDataSource =
false;
639 for (Content dataSource : dataSources) {
640 isSameDataSource = isSameDataSource || dataSource.getId() == objectId;
642 if (isSameDataSource) {
647 + IngestModuleInfo.IngestModuleType.DATA_SOURCE_LEVEL.toString() +
"-"
649 for (IngestModuleInfo ingestModuleInfo : ingestJob.getIngestModuleInfo()) {
650 boolean sameModule = ingestModuleInfo.getUniqueName().equals(uniqueName);
656 previousVersionRun = previousVersionRun || sameModule;
662 + IngestModuleInfo.IngestModuleType.FILE_LEVEL.toString() +
"-"
664 for (IngestModuleInfo ingestModuleInfo : ingestJob.getIngestModuleInfo()) {
665 boolean sameModule = ingestModuleInfo.getUniqueName().equals(uniqueName);
671 previousVersionRun = previousVersionRun || sameModule;
676 if (previousVersionRun) {
687 @Messages({
"IngestJobSettingsPanel.IngestModulesTableRenderer.warning.message=This ingest module has been run before on this data source.",
688 "IngestJobSettingsPanel.IngestModulesTableRenderer.info.message=A previous version of this ingest module has been run before on this data source."})
691 private static final long serialVersionUID = 1L;
693 List<String> tooltips =
new ArrayList<>();
697 tooltips.add(moduleTemplate.getDescription());
703 super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
706 setToolTipText(tooltips.get(row));
707 }
else if (1 == column) {
708 setIcon((Icon) value);
710 if (warningIcon.equals(value)) {
711 setToolTipText(Bundle.IngestJobSettingsPanel_IngestModulesTableRenderer_warning_message());
712 }
else if (infoIcon.equals(value)) {
713 setToolTipText(Bundle.IngestJobSettingsPanel_IngestModulesTableRenderer_info_message());
IngestJobSettingsPanel(IngestJobSettings settings, List< Content > dataSources)
IngestJobSettingsPanel(IngestJobSettings settings)
IngestModuleFactory getModuleFactory()
javax.swing.JSeparator jSeparator2
javax.swing.JLabel fileIngestFilterLabel
String getModuleVersionNumber()
void display(JPanel panel)
static List< FilesSet > getStandardFileIngestFilters()
void setEnabled(boolean enabled)
IngestModulesTableRenderer()
void updateSelectedFilter(String filterName)
void pastJobsButtonActionPerformed(java.awt.event.ActionEvent evt)
static synchronized FilesSetsManager getInstance()
javax.swing.JLabel descriptionLabel
void SelectAllModules(boolean set)
void addApplyButtonListener(ActionListener l)
javax.swing.JTable modulesTable
void jButtonSelectAllActionPerformed(java.awt.event.ActionEvent evt)
Class<?> getColumnClass(int c)
Map< String, FilesSet > getCustomFileIngestFilters()
void setIngestModuleTemplates(List< IngestModuleTemplate > moduleTemplates)
void globalSettingsButtonActionPerformed(java.awt.event.ActionEvent evt)
javax.swing.JButton pastJobsButton
boolean hasGlobalSettingsPanel()
javax.swing.JComboBox< String > fileIngestFilterComboBox
ImageIcon getIcon(IngestModuleModel module)
abstract void saveSettings()
javax.swing.JButton jButtonSelectAll
String[] getComboBoxContents()
static String getCreateNewFileIngestFilterString()
IngestJobSettings getSettings()
void setFileFilter(FilesSet fileIngestFilter)
javax.swing.ButtonGroup timeGroup
static FilesSet getDefaultFilter()
default boolean isDataSourceIngestModuleFactory()
SleuthkitCase getSleuthkitCase()
void setValueAt(Object aValue, int rowIndex, int columnIndex)
javax.swing.JScrollPane modulesScrollPane
void fileIngestFilterComboBoxActionPerformed(java.awt.event.ActionEvent evt)
boolean hasModuleSettingsPanel()
default boolean isFileIngestModuleFactory()
final IngestJobSettings settings
void jButtonDeselectAllActionPerformed(java.awt.event.ActionEvent evt)
List< IngestModuleTemplate > getIngestModuleTemplates()
Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
javax.swing.JPanel jPanel1
Object getValueAt(int rowIndex, int columnIndex)
synchronized static Logger getLogger(String name)
boolean isCellEditable(int rowIndex, int columnIndex)
javax.swing.JScrollPane jScrollPane1
static Case getCurrentCaseThrows()
IngestModuleModel selectedModule
String getModuleDisplayName()
String getModuleDescription()
javax.swing.JButton globalSettingsButton
final IngestModuleTemplate moduleTemplate
javax.swing.JPanel ingestSettingsPanel
IngestModuleGlobalSettingsPanel getGlobalSettingsPanel()
void setModuleSettings(IngestModuleIngestJobSettings settings)
IngestModuleIngestJobSettingsPanel getModuleSettingsPanel()
void customizeComponents()
javax.swing.JButton jButtonDeselectAll
static String normalize(String canonicalClassName)